【问题标题】:How to prevent d3 from triggering drag on right click?如何防止d3在右键单击时触发拖动?
【发布时间】:2013-06-14 13:20:14
【问题描述】:

我已经定义了一些按预期工作的拖动行为(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 中找到了对此问题的简短讨论。但是,我无法从这些 cmets 中弄清楚如何防止这种行为。

如何才能在右键单击时不触发拖动?

【问题讨论】:

  • 在dragstart事件中,你可以检查鼠标右键是否被点击(使用d3.event),如果是,不调用force.stop()。
  • 如何检查在d3.event 中单击了哪个鼠标按钮?我能找到的所有建议都像which、button 和keyCode 给我undefined。除此之外:我调用force.stop() 在用户拖动时停止布局算法。所以不调用它不会阻止拖动手势的发生。
  • 我认为d3.event 有一个成员sourceEvent 或类似的东西,可以让您访问实际事件。是的,你还需要preventDefault() 之类的东西。

标签: d3.js


【解决方案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

我不确定这是否是最优雅的解决方案,但它确实有效并且不是特别笨拙或大黑客。

【讨论】:

  • d3 v3.5.3,查看哪个按钮,可以使用d3.event.button
  • 对于v3.5.6,正确的方式应该是d3.event.sourceEvent.button而不是d3.event.button
  • 也应该等于 0 而不是 1 :)
  • @paradite 我使用的是 d3 版本 3.5.6,d3.event.sourceEvent.button 导致错误,因为 d3.event.sourceEvent 未定义。但d3.event.button 工作正常。
【解决方案2】:

对于 D3 v4,请参阅 drag.filter([filter])

如果指定了过滤器,则将过滤器设置为指定的函数并返回拖动行为。如果未指定过滤器,则返回当前过滤器,默认为。

drag.filter([filter])

右击:

.filter(['touchstart'])

可用的过滤器

mousedown、mousemove、mouseup、dragstart、selectstart、click、touchstart、touchmove、touchend、touchcancel

【讨论】:

  • 欢迎来到 SO。请阅读此how-to-answer。包含一个链接还不错,但随着时间的推移它可能无法访问。
【解决方案3】:

晚了一点,我遇到了同样的问题,我使用以下方法确保我的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]);
            }

        });

【讨论】:

    【解决方案4】:

    要处理所有拖动事件的监听器,可以使用下面的代码:

    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);
    

    【讨论】:

      【解决方案5】:

      实际上,对于不同版本的d3,您可能希望使用d3.event.which 而不是d3.event.sourceEvent.which 来检测您单击了哪个鼠标按钮。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-15
        • 2012-12-16
        • 1970-01-01
        • 2014-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多