D3 v4刷子和缩放相同的元素(没有鼠标事件冲突)

时间:2017-10-09 15:25:05

标签: d3.js

我的目标是构建一个同时使用d3-zoomd3-brush的D3(v4)图表,如下所示:

  1. 当鼠标位于x轴上方时,用户可以缩放(使用鼠标滚轮)或平移(通过向左和向右拖动)
  2. 当鼠标位于y轴上方时,用户可以缩放(使用鼠标滚轮)或平移(通过上下拖动)
  3. 当鼠标位于图表主体上方时,用户可以缩放(使用鼠标滚轮)或刷子将x域设置为特定范围
  4. 我已经设法在适当的轴上实现缩放和平移(根据要求1和2),但是在将两者结合在一起以实现要求3时遇到了问题。

    我根据文档/示例完成了以下操作:

    • 对于刷子,添加g SVG元素并在该元素上调用brush。该库在其中创建一个rectoverlay,并附加相应的鼠标事件,让我在该空间内绘制一个画笔区域。

    • 要进行缩放,请附加rect SVG元素并在该元素上调用zoom。该库连接适当的鼠标事件,以允许我使用鼠标滚轮在该空间内上下滚动。

    我遇到的问题是这两种方法的结合。由于zoombrush都会创建rect并处理鼠标事件,因此一次只能处理一个事件。最后创建的SVG元素“窃取”鼠标输入并且不会将其传播到另一个。如何在主图表区域将两者完美地结合在一起?

    我有一个显示问题的示例项目。它基于Angular& TypeScript但可以按如下方式运行:

    1. https://github.com/mattwilson1024/d3-zoom-and-brush
    2. 查看我的示例
    3. 运行npm installyarn install,然后npm startyarn start
    4. 运行应用
    5. 打开http://localhost:4200
    6. 您可以在两个轴上缩放和平移,或者刷主图表区域。可缩放区域的颜色为绿色和红色,以帮助调试
    7. 打开/src/app/char/chart.component.ts并取消注释第196行。这会移动x轴“缩放区域”(rect)以覆盖图表的整个主体。这意味着您可以使用滚轮在图表上的任何位置使用鼠标进行缩放x。
    8. 问题在于,现在缩放区域从画笔中“窃取”了鼠标事件,因此不再可以刷牙,而是翻过来。而不是d3-zoom设置的平移行为,我希望能够通过拖动鼠标进行刷动,但仍然可以使用滚轮进行缩放。

3 个答案:

答案 0 :(得分:0)

我今天遇到了同样的问题。正如您所指出的,缩放和刷子行为会窃取彼此的事件,因此您必须在不同的元素上建立它们。

本文概述了如何执行此操作: https://bfwg.github.io/ngx-drag-scroll/

本质上,它相当于创建一个SVG rect来专门处理缩放事件。您可以将刷子行为附加到svg组。

另见这里的演示: http://blog.scottlogic.com/2014/09/19/d3-svg-chart-performance.html

答案 1 :(得分:0)

问题是由事实d3.zoom(source)引起的,它为mousedowned事件添加了事件侦听器mousedownmousedowned调用event.stopImmediatePropagation,从而阻止其他mousedown个监听器(在您的情况下为brush)监听。由于您不想平移图表主体,因此可以删除此侦听器。

chartbody.on("mousedown.zoom", null)

这将阻止zoommousedown并停止事件传播。

答案 2 :(得分:0)

我也正面临着这个挑战,终于设法找到了可行的解决方案。 Zoom合并了event.stopPropagation()。这意味着在父元素中包含的元素上触发的任何事件都不会“冒泡”到父元素。 参见MDN以了解冒泡及其工作原理,并提供一个不错的示例https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture

这是我对它的工作方式的理解,以及为使我的解决方案有效而进行的合理化: 对于刷牙,事件将传播到祖先元素。就您而言,取决于svg-element。在您的情况下,您已将rect元素附加到svg,并将缩放行为附加到rect。因此,具有缩放比例的元素不是画笔元素的父元素,而是“叔叔/姨妈”,就好像您直接遍历DOM树一样,您将回到svg,而不是rect。 / p>

如果您改为将缩放行为附加到svg,使其成为使用brush动作的group元素的祖先,则这将使g元素上的动作冒泡到svg。现在,随着事件的发生,您的缩放也可以触发。在这种情况下,只需合并检查以查看事件的来源是什么,即是画笔操作还是缩放操作。根据检查结果,您可以应用缩放,当且仅当缩放动作是触发缩放事件触发的原因时,否则可以应用刷涂方法。