我的目标是构建一个同时使用d3-zoom和d3-brush的D3(v4)图表,如下所示:
我已经设法在适当的轴上实现缩放和平移(根据要求1和2),但是在将两者结合在一起以实现要求3时遇到了问题。
我根据文档/示例完成了以下操作:
对于刷子,添加g
SVG元素并在该元素上调用brush
。该库在其中创建一个rect
类overlay
,并附加相应的鼠标事件,让我在该空间内绘制一个画笔区域。
要进行缩放,请附加rect
SVG元素并在该元素上调用zoom
。该库连接适当的鼠标事件,以允许我使用鼠标滚轮在该空间内上下滚动。
我遇到的问题是这两种方法的结合。由于zoom
和brush
都会创建rect
并处理鼠标事件,因此一次只能处理一个事件。最后创建的SVG元素“窃取”鼠标输入并且不会将其传播到另一个。如何在主图表区域将两者完美地结合在一起?
我有一个显示问题的示例项目。它基于Angular& TypeScript但可以按如下方式运行:
npm install
或yarn install
,然后npm start
或yarn start
http://localhost:4200
d3-zoom
设置的平移行为,我希望能够通过拖动鼠标进行刷动,但仍然可以使用滚轮进行缩放。答案 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
事件添加了事件侦听器mousedown
。 mousedowned
调用event.stopImmediatePropagation
,从而阻止其他mousedown
个监听器(在您的情况下为brush
)监听。由于您不想平移图表主体,因此可以删除此侦听器。
chartbody.on("mousedown.zoom", null)
这将阻止zoom
听mousedown
并停止事件传播。
答案 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。现在,随着事件的发生,您的缩放也可以触发。在这种情况下,只需合并检查以查看事件的来源是什么,即是画笔操作还是缩放操作。根据检查结果,您可以应用缩放,当且仅当缩放动作是触发缩放事件触发的原因时,否则可以应用刷涂方法。