D3 v4在同一元素上进行画笔和缩放(没有鼠标事件冲突) [英] D3 v4 Brush and Zoom on the same element (without mouse events conflicting)
问题描述
我的目标是建立一个同时使用 d3-zoom 和一起 d3-brush ,
- 当鼠标位于x轴上时,用户可以缩放(使用鼠标滚轮)或平移(通过向左和向右拖动)
- 当鼠标位于y轴上时,用户可以缩放(使用鼠标滚轮)或平移(通过上下拖动)
- 将鼠标置于统计图主体上方时,用户可以缩放(使用鼠标滚轮)或进行笔刷以将x域设置为特定范围
我已经设法在适当的轴上实现了缩放和平移(按照要求1和2),但是在将两者结合在一起以达到要求3时遇到了问题.
根据文档/示例,我已经完成了以下操作:
-
要进行刷牙,请附加一个
g
SVG元素,然后在该元素上调用brush
.该库在其中创建一个包含类overlay
的rect
,并附加适当的鼠标事件以允许我在该空间内绘制画笔区域. -
要缩放,请附加一个
rect
SVG元素,然后在该元素上调用zoom
.该库连接了适当的鼠标事件,以使我可以在该空间内使用鼠标滚轮上下滚动.
我遇到的问题是这两种方法的结合.因为zoom
和brush
都创建了rect
并处理鼠标事件,所以一次只能工作一个.最后创建的SVG元素会窃取"鼠标输入,并且不会将其传播到其他输入.我如何才能使两者在主图表区域完美搭配?
我有一个显示问题的示例项目.它基于Angular& TypeScript,但可以按以下方式运行:
- 在 https://github.com/mattwilson1024/d3-zoom-和画笔
- 先运行
npm install
或yarn install
,然后运行npm start
或yarn start
,运行应用程序
- 打开
http://localhost:4200
- 您可以在两个轴上缩放和平移,或在主图表区域上进行笔刷.可缩放区域的颜色为绿色和红色,以帮助调试
- 打开/src/app/char/chart.component.ts并取消注释线196.这将移动x轴缩放区域"(矩形)以覆盖整个图表.这意味着您可以使用滚轮在图表上的任意位置用鼠标进行x缩放.
- 问题在于,现在缩放区域从画笔窃取"了鼠标事件,因此不再可能进行画笔绘制,而是进行平移.除了希望
d3-zoom
设置的平移行为外,我希望能够通过拖动鼠标进行画刷,但仍然可以使用滚轮进行缩放.
我最终也面对了这一挑战,设法找到了可行的解决方案. Zoom合并了event.stopPropagation().这意味着在父元素中包含的元素上触发的任何事件都不会冒泡"到父元素.
参见MDN以了解冒泡及其工作原理,并提供一个很好的示例
如果您将缩放行为附加到svg,以使其成为使用brush动作的group元素的祖先,则这将使g元素上的动作冒泡到svg.现在,随着事件冒泡,您的缩放也可以触发.在这种情况下,只需合并检查以查看事件的来源是什么,即是画笔操作还是缩放操作.根据检查结果,您可以应用缩放,如果且仅当缩放动作是触发缩放事件触发的原因时,否则可以应用刷涂方法. My goal is to build a D3 (v4) chart that uses both d3-zoom and d3-brush together, as follows: I have managed to implement both zooming and panning on the appropriate axes (as per requirements 1 & 2), but am having problems combining the two together to achieve requirement 3. I have done the following, based on the docs/examples: For brushing, append a For zooming, append a The problem I have is in the combination of these two approaches. Because both I have an example project which shows the problem. It's based on Angular & TypeScript but can be run as follows:
I finally managed to get a working solution to this challenge as I was facing it too. Zoom incorporates event.stopPropagation(). This means that any events triggered on elements contained within a parent element will not "bubble up" to the parent element.
See MDN to understand bubbling and how it works, with a nice example https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture This is how I understand it working and what I have rationalised to get my solution working:
For brushing, the event will propagate up to ancestor elements. In your case up to the svg-element. In your case you have appended a rect-element to the svg and attached your zoom behaviour to the rect. Therefore, the element with the zoom is not a parent of the element with the brush, but rather an "uncle/aunt", as if you traversed directly back up the DOM tree you would get back to the svg and never the rect. If you instead attach the zoom behaviour to the svg so that it is an ancestor of the group element with the brush action, this will allow the action on the g element to bubble up to the svg. Now your zoom can also fire as the event will bubble up. In this case just incorporate a check to see what the source of the event was, i.e. was it the brush or zoom action. Based on the result of the check you can then apply the zoom, if and only if, the zoom action is what triggered the zoom event to fire, otherwise apply the brushing method. 这篇关于D3 v4在同一元素上进行画笔和缩放(没有鼠标事件冲突)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
g
SVG element and call the brush
on that element. The library creates a rect
with class overlay
inside that, and attaches the appropriate mouse events to let me draw a brush region inside that space.rect
SVG element and call the zoom
on that element. The library hooks up the appropriate mouse events to allow me to scroll up and down with the mouse wheel inside that space.zoom
and brush
create a rect
and handle mouse events, only one works at a time. The SVG element that is created last "steals" the mouse input and does not propagate it to the other. How can I get the two to play nicely together on the main chart area?
npm install
or yarn install
, then npm start
or yarn start
http://localhost:4200
d3-zoom
sets up, I want to be able to brush by dragging the mouse, but still zoom with the wheel.