繁体   English   中英

D3区分具有拖动行为的元素的单击和拖动

[英]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处理程序中检查这一点,以查看是否正在进行任何拖动操作。

另见这个问题的答案。

您可以区分clickdragstart ,但很难区分mousdowndragstart

当您开始拖动操作时,将触发dragstart ,这意味着当您执行mousedown 这就是为什么。 无论何时click ,都会triggered dragstart clickmousedown + 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触发其dragstartdragend事件,但不会onDrag事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM