[英]D3 Differentiate between click and drag for an element which has a drag behavior
我无法使用D3.js v3成功区分绑定到两者的元素上的click
事件和drag
事件。 下面的代码中的圆圈被分配了拖动行为以及click
侦听器。 在这里演示
var dragGroup = d3.behavior.drag()
.on('dragstart', function () {
console.log('Start Dragging Group');
})
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
});
var dragCircle = d3.behavior.drag()
.on('dragstart', function () {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
console.log('Start Dragging Circle');
})
.on('drag', function (d, i) {
d.cx += d3.event.dx;
d.cy += d3.event.dy;
d3.select(this).attr('cx', d.cx).attr('cy', d.cy);
});
var svg = d3.select('body').append('svg').attr('viewBox', '-50 -50 300 300');
var g = svg.selectAll('g').data([{
x: 10,
y: 10
}])
.enter().append('g').call(dragGroup);
g.append('rect').attr('width', 100).attr('height', 100);
g.selectAll('circle').data([{
cx: 90,
cy: 80
}]).enter()
.append('circle')
.attr('cx', function (d) {
return d.cx;
})
.attr('cy', function (d) {
return d.cy;
})
.attr('r', 30)
.call(dragCircle)
.on('click', function () {
console.log('clicked circle');
});
每当我单击示例中的圆圈时,我都会让控制台记录drag
事件以及click
事件。 拖动时我也会得到相同的行为,首先记录drag
事件,然后在mouseup
上记录click
事件。
分别处理这些事件的正确方法是什么?
用例是尝试在树布局中处理节点单击和节点拖放。
缺少的关键位是检查是否已阻止事件的默认行为。 也就是说,有一个匹配同级d3.event.preventDefault()
- d3.event.defaultPrevented
。 您需要在click
处理程序中检查这一点,以查看是否正在进行任何拖动操作。
另见这个问题的答案。
您可以区分click
和dragstart
,但很难区分mousdown
和dragstart
。
当您开始拖动操作时,将触发dragstart
,这意味着当您执行mousedown
。 这就是为什么。 无论何时click
,都会triggered
dragstart
。 ( click
是mousedown
+ mouseup
)。
因此, 防止点击被触发应该有效 。 在你的代码中,你应该像Lars Kotthoff暗示的那样添加preventDefault。 但是不要把它放在dragstart函数中:
var dragCircle = d3.behavior.drag()
.on('dragstart', function () {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault(); <-- Remove This
console.log('Start Dragging Circle');
})
并将其添加在正确的地方(在点击功能),并将其与D3写正确(d3.event。defaultPrevented)
g.selectAll('circle').data([{
cx: 90,
cy: 80
}]).enter()
.append('circle')
.attr('cx', function (d) {
return d.cx
})
.attr('cy', function (d) {
return d.cy
})
.attr('r', 30)
.call(dragCircle)
.on('click', click);
function click(d) {
if (d3.event.defaultPrevented) return; <-- Add d3.event.defaultPrevented
console.log('clicked');
}
请参阅更新版本 。 现在,拖动时,不再触发click
。
请记住,单击时,仍会触发dragstart
。 (但不是drag
)
d3.event.sourceEvent.preventDefault()
不能按预期工作,或者它不一致。
我遇到了这个问题,为了区分这两个事件,我在onDrag
事件中使用了一个布尔值isDragged
。 因此,如果设置了此值,则在对象上执行drag
事件(如果不是),则执行click
事件。 正常点击对象dragend
触发其dragstart
和dragend
事件,但不会onDrag
事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.