带有 d3 的可刷和可缩放时间线



我想制作一个时间轴,用户可以在其中选择滚动缩放或选择要缩放的区域。 有一些第一种类似的例子: https://bl.ocks.org/mbostock/4015254 或者用画笔放大区域: https://bl.ocks.org/mbostock/f48fcdb929a620ed97877e4678ab15e6
但我找不到同时做到这两点的例子。我怎样才能同时做到这两点?还是我错过了任何示例?

这不是最直接的实现。正如您将注意到的,基于画笔的缩放不依赖于d3.zoom而是通过侦听器执行缩放,这些侦听器触发事件以执行缩放轴并相应地移动绘图元素所需的任何操作。

相比之下,所有基于滚动的缩放示例通常依赖于d3.zoom,它利用d3.zoom()行为来跟踪平移/缩放时对绘图执行的所有转换,并全权负责更新各种图表元素。困难在于这两种方法完全不同,如果您通过刷笔手动更改图表视图,则需要找出一种方法来更新d3.zoom引用的内部缩放转换,以便它知道通过基于画笔的缩放事件所做的更改。

这根本不容易做到,因为d3.zoom不是为从其他地方提供信息而设计的,并且执行的转换的内部记录不是可更新/可变的。您可以通过selection.call(zoom.transform, d3.zoomIdentity);更新转换,但不幸的是,这也触发了与实际缩放行为相关的一大堆事件,这不是您想要的,因为您已经使用基于画笔的缩放处理了所有缩放行为。我能够用来重置缩放转换的一个丑陋但有效的解决方法是改变绑定到d3.zoom行为的 DOM 节点的实际.__zoom字段,如下所示:

// WARNING: Ugly mutation of __zoom property of pan/scroll-zoom rect to
// reset the transform without having to fire events associated with zoom
// d3.select(".zoom").node().__zoom = {k: 1, x: 0, y: 0}; <-- Fails since __zoom contains other hidden objects
scrollZoom.node().__zoom["k"] = 1;
scrollZoom.node().__zoom["x"] = 0;
scrollZoom.node().__zoom["y"] = 0;

例如:如果您想要一个用于矩形缩放的 2D 画笔,还需要基于d3.zoom的缩放来平移和鼠标滚动,那么无论何时使用 2D 画笔进行缩放,您都需要将 d3.zoom 转换重置回标识转换,如上所示。这可以防止在将基于 2D 画笔的缩放操作与平移/鼠标滚动操作链接在一起时,平移/滚动响应中出现丑陋和不和谐的抖动,因为记录中的变换与显示的视图不同步d3.zoom由于基于 2D 画笔的缩放在 d3.zoom 不知情的情况下更改视图)。

以下是需要注意的其他重要事项:

d3.zoom有一个限制,因为它目前仅支持 X 轴和 Y 轴的通用缩放比例(源)。不幸的是,这意味着无法将基于 2-D 画笔的缩放映射到基于d3.zoom的方法,因为基于 2D 画笔的缩放在 X 和 Y 中产生不同的缩放缩放比例。如果你想用最少的问题做事,使用一致的方法,我建议你考虑使用 d3.xyzoom。这是一个d3.zoom分支,它实现了对 X 轴和 Y 轴不同比例的支持。这将使您能够计算任何 2D 画笔选择的相应 X 和 Y 缩放缩放和平移值,然后您可以将其输入d3.zoom,从而使您能够使用通用方法执行所有缩放(这也会导致最少的代码重复)。

话虽如此,如果您只对基于 1-D 画笔的缩放感兴趣,您应该能够将其映射到 d3.zoom 方法,这样您就不必处理 2 条不同的路径来处理图表中所有轴和其他图形元素的视图和缩放。这是一个很好的例子:

https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172

对于这篇文章的长度,如果它有点漫无边际,我深表歉意。我正在努力在几天内对我的工作进行整理,我会尝试回到这里并在我这样做时发布一个链接。我一周前才开始学习D3,所以我一直在学习。

最新更新