我是D3.js的新手,我想使用图形布局。我有这个演示设置了一个非常简单的图形,遵循D3中内置的力导向布局。
我想要做的是能够关闭图形布局算法(例如,当用户按下空格时)然后仍然能够拖动节点并转动力导向布局重新开始。
现在我已将其设置为在击中空间时停止力导向布局:
d3.select("body")
.on("keydown", function() {
if (d3.event.keyCode == 32) {
if (forceActive) {force.stop();} else {force.resume();}
}
});
问题是每次拖动节点时都会重新启动强制布局。我已经将它缩小到(基本上)节点上的调用方法被绑定到强制布局的拖动方法。
即。这段链接代码:
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
...
.call(force.drag);
我想我可能要做两件事:
我想知道之前是否已完成此操作,以及如何操作(根本不会使用我猜测如何操作)。
答案 0 :(得分:6)
首先,关于您的明确问题:call()
方法有什么作用?
在d3中,call
只是一个方便的功能,可以将其他功能彻底改变。做
node.call( force.drag );
实际上和做
一样force.drag( node );
唯一的区别是选择中的call
方法总是返回选择,因此您可以将其他方法链接到它。
所以现在你的问题是,force.drag( selection )
做了什么?它创建了用于处理拖动行为的鼠标和触摸事件的事件侦听器。这些事件侦听器更新节点数据对象的位置,但它们也会重新启动强制布局。
如果您不想使用默认的强制布局拖动行为,请不要在选择中调用force.drag
方法。
只要能够自定义拖动行为以使其不重新启动强制布局,看起来就不能用force.drag
执行此操作(无论如何都不能更改源代码) 。 但是,您可以通过创建自己的drag behaviour object并将其绑定到节点来访问大多数与拖动相关的功能。
然后,在您的拖动事件处理程序中,您将更新节点数据对象的x和y位置,并重绘节点以及连接到它的任何链接。如果你的图表不是太大,你可以通过重新调用tick
函数来重绘所有元素以匹配他们的数据;如果您的图表 大,您可能希望存储对数据对象中实际元素的引用,以便您可以快速找到正确的链接。
使用拖动行为(没有强制布局)的一些示例可以帮助您入门: