我目前正致力于力量模拟。 Here's the fiddle如果你需要它。这一部分给我带来了一些麻烦 - 我尝试用于链接,而不是节点,情况类似,所以我们可以看到工作和非工作的区别:
function linkRender(selection) {
selection
.data(links)
.enter().append("line")
.attr("stroke-width",2)
.attr("stroke","black")
}
let link = svg.selectAll("line").call(linkRender);
这里,call()
应该返回选择,即链接线。但是,在selection.on()
中渲染链接时,如果我使用link
变量进行处理,则无法正常呈现,这对我的困扰很大:
simulation.on("tick",byFrame);
function byFrame() {
// This doesn't work!
link
.attr("x1", d => d.source.x )
.attr("y1", d => d.source.y )
.attr("x2", d => d.target.x )
.attr("y2", d => d.target.y )
// But this works!
svg.selectAll("circle")
.attr("cx",d => d.x )
.attr("cy",d => d.y )
}
如果我将link
变量分配给linkRender()
旧方式,即
let link = linkRender(svg.selectAll("line"))
只要我设置linkRender()
以返回代码(return selection.data(links).etc
),渲染就可以了。
最后,这里是link
和svg.selectAll("line")
的比较:
所以我很想知道发生了什么。提前谢谢!
答案 0 :(得分:2)
您的陈述不相同,因此无法比较。 selection.call()
上的文档告诉我们:
只调用指定的函数一次,传入此选择以及任何可选参数。返回此选择。
这应该从字面上理解:返回这个选择意味着完全选择调用指定函数。由于在该调用之前没有行,因此在调用.call()
时,您的选择将为空。虽然您可以在该函数中成功使用此空选择来绑定数据并附加行,但这不会改变原始选择。
由于
选择是不可变的。
.call()
方法仍会返回原始的,即空的选择,然后将其分配给link
。很容易看出,这与之后选择新添加的行或从修改后的函数返回输入选择时的其他解决方案不同。
它实际上适用于节点,因为在byFrame()
中,您不是通过node
访问它们,而是通过svg.selectAll("circle")
来访问它们。
我认为这个应用程序使用
let link = linkRender(svg.selectAll("line"));
将是要走的路。正如您已经提到的,这将需要linkRender()
正确返回选择。