【问题标题】:Short-circuiting events in d3?d3中的短路事件?
【发布时间】:2017-02-13 18:53:37
【问题描述】:

我有一个包含许多形状的 D3 (v4) 可视化,在某些情况下,它们会在大约三秒的过程中动画到新的位置。这些形状具有单击和鼠标悬停事件侦听器,我希望仅在可视化不移动时才处于活动状态。

实现这一点的天真方法很简单。我有一个名为 is_animating 的布尔变量,在动画开始时设置为 true,在回调时设置为 false,所以我只是将它添加到事件侦听器中:

shapes.on("click", function(d) {
  if (is_animating) {
    return;
  }
  // otherwise, business as usual
})

这很好,但是我计划向形状添加大量事件侦听器,如果有更优雅的方法来拦截冒泡中较高的事件并且只执行一次而不是将此检查添加到每个事件。但我不完全理解d3.event 以及它如何处理冒泡。是否有一个简单的“主事件监听器”,如果你愿意,它会在用户尝试做某事时触发,如果is_animating 为真,这可能会使事件短路?

【问题讨论】:

    标签: javascript d3.js events dom-events event-bubbling


    【解决方案1】:

    在 D3 转换 API 中有一种方法可以控制是否存在与给定节点关联的任何活动转换 (d3.active)。

    您可以使用它来检测节点上的活动转换,而无需引入额外的变量。

    shapes.on("click", function(d) {
      if (d3.active(this)) {
        return;
      }
      // otherwise, business as usual
    })
    

    【讨论】:

    • 谢谢,很高兴知道!这仍然意味着要检查每个听众,但非常有用的信息。
    【解决方案2】:

    如果它适用于您的设置方式,您可以等到过渡结束后再注册事件侦听器:

    shapes
      .transition()
      .attr(...) // apply new positions, styles, etc
      .on('end', function() {
        // called per element once its transition has completed
        d3.select(this)
          .on('click', function() { /* business as usual */ })
      })
    

    另一个可能对您有用的一点是,您不必在shapes 选择上注册事件侦听器,这会产生多个侦听器。相反,您可以订阅他们父母的事件。如果该父级是 d3 选择中的 svg,它看起来像这样

    svg // assumes svg is a d3 selection containing every shape
      .on('click', function() {
        // to get the clicked element
        d3.select(d3.event.target)
          .attr(...)
    
        // or, if you just want d, the datum of the shape
        // that was clicked:
        var d = select(d3.event.target).datum()
      })
    

    我认为没有一种方法可以防止您描述的冒泡。我不知道为什么;我希望它能够工作,但我的测试没有成功。应该注意的是,即使您能够停止传播,它也将是从子到父的传播,而不是从父到子的传播。

    【讨论】:

    • 两个好主意!我同意似乎应该有一个冒泡的解决方案,但我也无法让它发挥作用——关于方向的好点。也许解决方案是在捕获阶段进行拦截?
    猜你喜欢
    • 2021-12-26
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多