为什么 d3.js v3 在 v2 没有实现缩放时会破坏我的力图?

IT技术 javascript svg d3.js force-layout
2021-02-19 14:52:45

我有一个使用 d3.js 创建的力布局

我想同时拥有可拖动力布局的正常功能以及缩放功能。

我基本上已经从(http://jsfiddle.net/nrabinowitz/QMKm3/复制/粘贴了缩放代码这与 Mike Bostock 在 ( http://bl.ocks.org/mbostock/3680957 ) 中使用的缩放方式相同

这是我的代码:http : //jsfiddle.net/kM4Hs/6/

缩放工作正常,但我无法在强制布局中选择单个节点并将它们拖动。

我发现罪魁祸首是两位作者都使用 d3.v2.js 而不是较新的 d3.v3.js。当我将导入更改为 v2 时,它运行良好。但是,如果可能,我想使用 v3。

<script type='text/javascript' src='http://d3js.org/d3.v3.min.js'></script>

相对

<script type='text/javascript' src='http://d3js.org/d3.v2.min.js'></script>

为什么当 v2 没有时 v3 会破坏力布局,更重要的是,我该怎么做才能修复它?

提前致谢!

1个回答

如果您仔细阅读发行说明,您将看到 2.x 的最终版本 (2.10.3) 和最新版本 3.2.7 之间所有更改的完整说明。特别是从 3.2.2 版开始:

通过不阻止默认行为或停止传播,更好地处理 d3.behavior.drag、d3.behavior.zoom 和 d3.svg.brush 中的拖动手势。例如,mousedown 现在可以更改焦点,iframe 外的 mouseup 可以正常工作,并且 touchstart 不会断断续续。

因此,在 V2 中,通过停止缩放事件的传播,拖动行为可以优先于缩放行为。在 V3 中,这不再自动发生,让您可以选择哪种行为优先以及何时优先。

如果您想在拖动节点时给予拖动行为优先级,那么您需要在拖动时停止对输入事件的传播以便这些事件不会同时被缩放行为解释为平移。在 dragstart 上停止传播就足够了:

var drag = d3.behavior.drag()
    .on("dragstart", function() { d3.event.sourceEvent.stopPropagation(); })
    .on("drag", function() { /* handle drag event here */ });

如果使用强制布局,代码为:

var drag = force.drag()
    .on("dragstart", function() { d3.event.sourceEvent.stopPropagation(); });

工作示例:

拖动和缩放

注意:结合这两种行为意味着手势解释是不明确的并且对位置高度敏感。单击一个圆圈被解释为拖动该圆圈,而单击一个像素远可以解释为平移背景。组合这些行为的更稳健的方法是使用模态。例如,如果用户按住 SPACE 键,无论单击位置如何,单击和拖动都会被解释为平移,而不是拖动。这种方法通常用于商业软件,如 Adob​​e Photoshop。

我已经意识到,在力布局上执行此操作似乎会通过重新调整其他一些节点/边来覆盖布局响应节点移动的自然方式。我通过让拖动方法也更新所有链接来解决这个问题,所以这很容易修复。我无法弄清楚的部分是修复力功能。我尝试在拖动结束时执行 force.resume(),但是在恢复强制功能的同时,它还重置了我拖动的任何节点的位置(我在拖动结束时设置 d.fixed=true,因为我想修复拖动的节点)。
2021-04-16 14:52:45
查看粘性力布局示例force.drag文档我刚刚更新了它们。
2021-05-05 14:52:45
有人知道为什么缩放在 webkit 中效果很好,但在 Firefox 中,捏合手势会增加整个页面的缩放系数吗?我试图用元视口属性解决这个问题,但它没有帮助。
2021-05-12 14:52:45
我也遇到了力布局的问题。从阅读张贴@mbostock的链接,我的答案是创造var dragforce.drag代替d3.behavior.drag
2021-05-12 14:52:45
@mbstock 谢谢。粘性力布局示例为我节省了大量时间!
2021-05-16 14:52:45