我可以重新创建以下1000次并且有足够的理解来这样做。但是,我试图绕过一些我只是做的事情,而不是理解:
var w = 900,
h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
.attr("style", "border: 1px solid grey;")
.on("mousemove", fn)
var force = d3.layout.force()
.size([w, h])
.on("tick", tick)
.gravity(0)
.charge(0)
.start()
function fn() {
var m = d3.mouse(this);
var point = {x: m[0], y: m[1]};
d3.select("#output").text(force.nodes().length)
var node = svg
.append("circle")
.data([point])
.attr("cx", function(d) {return d.x})
.attr("cy", function(d) {return d.y})
.attr("r", 0.1)
.transition().ease(Math.sqrt)
.attr("r", 5)
.transition().delay(1000)
.each("end", function() {
force.nodes().shift()
})
.remove()
force.nodes().push(point)
force.start()
}
function tick() {
svg.selectAll("circle")
.attr("cx", function(d) {return d.x})
.attr("cy", function(d) {return d.y})
}
特别是数据绑定部分我不确定。
在函数fn()中(在svg空间的mousemove上)我们定义一个新点,我们需要用它做两件事;将它推入force.nodes(),以便可以通过力布局中配置的力来操纵点的x和y坐标,我们需要使用点的坐标来创建和操作可视化。
所以我们首先创造了这一点。然后,我们构建一个圆圈来表示这一点。我们将这一点推入force.nodes()并在短暂的延迟之后,我们从force.nodes()数组中删除了可视化和点。
我不明白的是,可视化和阵列中的点如何保持连接"?
猜想:数据点是力布局不断更新x和y属性的对象。有一个"链接"将此对象绑定到circle元素。因此,圆形对象可以轻松访问和使用该对象,但不是没有我们控制该过程。圆被定义为在其创建时具有cx和cy,但我们需要继续访问底层数据以更新其cx和cy?
如果是这样的话,该对象如何共享"由force.nodes()和圆元素?
或者我是否离开了标记?
此外,我已经阅读了很多关于此的文档,但我觉得这是javascript更内在的东西,而不是d3,所以我在目前为止所阅读的任何文献中都没有详细说明。< / p>
答案 0 :(得分:2)
强制布局更新的数据结构与可视化(即DOM元素)之间的链接是tick
事件处理函数。 tick
事件由力布局生成,表示力模拟已经进行了另一步(即滴答)并且其内部状态已经改变。这表明可视化需要更新。
实现此链接有两个部分。首先,由力布局(即链接和节点)操作的数据需要绑定到DOM元素。这是使用通常的.selectAll().data().enter().append()
模式完成的,通常在初始化代码中,有时在tick
事件处理函数中。这建立了数据和DOM元素之间的联系。
第二部分是强制布局改变位置时更新DOM元素的代码。这就是tick
事件处理函数中发生的情况。如果您不添加或删除元素,通常不需要重新绑定数据,通常您将看不到.selectAll().data()
模式,而只会看到实际根据已绑定到元素的数据更新位置的代码(在你的情况下,即使你正在更改元素,这仍然有效,因为数据绑定发生在更新力布局数据的函数中)。
作为一个实验,采用任意的力布局示例并删除tick
事件处理函数 - 即使强制布局正在运行,您也会发现没有任何事情发生。