Как предотвратить d3 от запуска перетаскивания по правому клику?
Я определил некоторое поведение перетаскивания, которое работает как ожидалось следующим образом (код в CoffeeScript):
nodeDrag = d3.behavior.drag()
.on("dragstart", (d, i) ->
force.stop())
.on("drag", (d, i) ->
d.px += d3.event.dx
d.py += d3.event.dy
d.x += d3.event.dx
d.y += d3.event.dy
tick())
.on("dragend", (d, i) ->
force.resume()
d.fixed = true
tick())
// ...
nodes = vis.selectAll(".node")
.data(graph.nodes)
.enter()
.append("g")
// ...
.call(nodeDrag)
Теперь я пытаюсь создать собственное поведение для правых кликов на узлах. Однако это вызывает "dragstart" и "drag", т.е. После того, как я вызываю e.preventDefault()
в событии "contextmenu", вопрос node привязан к указателю мыши и следует за ним, пока я не сделаю другой (слева) щелчок чтобы заставить освобождение (я предполагаю, что e.preventDefault()
также вызывает "dragend", чтобы никогда не срабатывать).
Я нашел краткое обсуждение этой проблемы в потоке в группах Google и обсуждение проблем d3 в Github. Тем не менее, я не могу понять из этих комментариев, как предотвратить это поведение.
Как я могу не вызвать перетаскивание по правому клику?
Ответы
Ответ 1
Я нашел возможность ограничить жесты перетаскивания только левой кнопкой мыши.
Он включает дополнительное поле, которое записывает, когда был начат жест:
dragInitiated = false
Остальная часть кода затем модифицируется для регистрации инициирования и завершения желаемых жестов перетаскивания на "dragstart" и "dragend" соответственно. Действия "перетаскивания" затем выполняются только в том случае, если жесты перетаскивания были правильно запущены.
nodeDrag = d3.behavior.drag()
.on "dragstart", (d, i) ->
if (d3.event.sourceEvent.which == 1) # initiate on left mouse button only
dragInitiated = true # -> set dragInitiated to true
force.stop()
.on "drag", (d, i) ->
if (dragInitiated) # perform only if a drag was initiated
d.px += d3.event.dx
d.py += d3.event.dy
d.x += d3.event.dx
d.y += d3.event.dy
tick()
.on "dragend", (d, i) ->
if (d3.event.sourceEvent.which == 1) # only take gestures into account that
force.resume() # were valid in "dragstart"
d.fixed = true
tick()
dragInitiated = false # terminate drag gesture
Я не уверен, что это самое элегантное решение, но оно работает и не является исключительно неуклюжим или большим взломом.
Ответ 2
Немного поздно для вечеринки, у меня была такая же проблема, и я использовал следующий метод, чтобы убедиться, что мой drag
работает только для left click
.
var drag = d3.behavior.drag()
.on('drag', function () {
console.log(d3.event.sourceEvent.button);
if(d3.event.sourceEvent.button == 0){
var mouse = d3.mouse(this);
d3.select(this)
.attr('x', mouse[0])
.attr('y', mouse[1]);
}
});
Ответ 3
Чтобы обрабатывать всех слушателей события перетаскивания, вы можете использовать следующий код:
function dragChartStart() {
if(d3.event.sourceEvent.button !== 0) {
console.log("not left click");
return;
}
console.log("dragStart");
}
function dragChartEnd() {
if(d3.event.sourceEvent.button !== 0) {
console.log("not left click");
return;
}
console.log("dragEnd");
}
function dragChartMove() {
if(d3.event.sourceEvent.button !== 0) {
console.log("not left click");
return;
}
console.log("dragMove");
}
var dragBehavior = d3.behavior.drag()
.on("drag", dragChartMove)
.on("dragstart", dragChartStart)
.on("dragend", dragChartEnd);
Ответ 4
для D3 v4 см. drag.filter([filter])
Если задан фильтр, он устанавливает фильтр в указанную функцию и возвращает поведение перетаскивания. Если фильтр не указан, возвращает текущий фильтр, который по умолчанию.
drag.filter([filter])
для правого клика:
.filter(['touchstart'])
Доступные фильтры
mousedown, mousemove, mouseup, dragstart, selectstart, click, touchstart, touchmove, touchhend, touchcancel
Ответ 5
На самом деле с другой версией d3
вы можете использовать d3.event.which
вместо d3.event.sourceEvent.which
, чтобы определить, какую кнопку мыши вы нажали.