我已经定义了一些按预期工作的拖动行为,如下所示(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”,即在我在“contextmenu”事件上调用e.preventDefault()
之后,有问题的节点会粘在我的鼠标指针上并跟随它直到我再做一次(左)单击强制释放(我假设e.preventDefault()
也导致“dragend”永远不会发射。
我在thread on Google Groups和discussion in d3's issues on Github中找到了对此问题的简短讨论。但是,我无法从这些评论中弄清楚如何防止这种行为。
如何在右键单击时不触发拖动?
答案 0 :(得分:9)
我发现只能将拖动手势限制为鼠标左键。
它涉及一个记录手势何时启动的附加字段:
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
我不确定这是否是最优雅的解决方案,但它确实有效,并不是特别笨拙或大黑客。
答案 1 :(得分:2)
对于D3 v4,请参阅drag.filter([filter])
如果指定了filter,则将过滤器设置为指定的函数并返回拖动行为。如果未指定filter,则返回当前过滤器,默认为。
drag.filter([filter])
右键单击:
.filter(['touchstart'])
可用过滤器
mousedown,mousemove,mouseup,dragstart,selectstart,click,touchstart,touchmove,touchend,touchcancel
答案 2 :(得分:1)
派对迟到了,我遇到了同样的问题,我使用以下方法确保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 :(得分:1)
要处理拖动事件的所有侦听器,您可以使用以下代码:
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 :(得分:0)
实际上,对于sum(numbers)
的不同版本,您可能希望使用d3
代替d3.event.which
来检测您点击的鼠标按钮。