D3.js 如何在基础数据更改时更新D3 force布局的元素
我正在使用一个force布局示例()在我的网站上显示一个网络 我允许用户在任何给定时间选择要查看的链接类型。我注意到,当我选择查看链接类型A,然后添加链接类型B,然后删除链接类型A时,类型B的剩余链接将以A颜色显示 这是用于将链接添加到svg图的代码。我正在通过添加和删除链接来更改数组D3.js 如何在基础数据更改时更新D3 force布局的元素,d3.js,force-layout,D3.js,Force Layout,我正在使用一个force布局示例()在我的网站上显示一个网络 我允许用户在任何给定时间选择要查看的链接类型。我注意到,当我选择查看链接类型A,然后添加链接类型B,然后删除链接类型A时,类型B的剩余链接将以A颜色显示 这是用于将链接添加到svg图的代码。我正在通过添加和删除链接来更改数组this.links。如您所见,我设置了class属性,但它没有更新-它仍然是链接A的类型 var path = svg.append("svg:g") .selectAll("path") .da
this.links
。如您所见,我设置了class属性,但它没有更新-它仍然是链接A的类型
var path = svg.append("svg:g")
.selectAll("path")
.data(this.links)
.enter()
.append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
我目前通过更新tick函数中的class属性来解决这个问题,但这会导致很多不必要的工作
我读到enter操作返回了exist元素和新元素的合并选择,因此attr操作应该更新exist元素并设置新元素
我遗漏了什么?在上有一个示例,显示如何从强制导向布局中添加和删除节点。必须分别处理链接和节点,然后重新启动force布局
function restart() {
var link = vis.selectAll("line.link")
.data(links, function(d) { return d.source.id + "-" + d.target.id; });
link.enter().insert("svg:line", "g.node")
.attr("class", "link");
link.exit().remove();
var node = vis.selectAll("g.node")
.data(nodes, function(d) { return d.id;});
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
nodeEnter.append("svg:image")
.attr("class", "circle")
.attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
.attr("x", "-8px")
.attr("y", "-8px")
.attr("width", "16px")
.attr("height", "16px");
nodeEnter.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.id });
node.exit().remove();
force.start();
}
我已经找到了答案
答案是我需要对selectAll.data的结果调用attr操作符,而不是对append操作符的结果调用attr操作符。这还不够。我正在添加和删除链接,问题是它没有顺序。当我选择查看类型A的链接时,链接数组是[A1,A2,A3],然后我选择查看类型B的链接,数组是[A1,A2,A3,B1,B2],然后我选择不查看类型A的链接,数组是[B1,B2]。D3然后选择保留2个元素并删除3个元素,但我必须更新这两个元素,因为它们当前绑定到A1和A2,我需要它们绑定到B1和B2。我通过保存vis.selectAll(“g.Node”).数据(节点)并进行更新来做到这一点。如果您创建一个JSFIDLE来显示您当前正在做什么以及问题是什么,那么我们可能能够帮助找到更好的解决方案。我知道这是一篇老文章,但我相信我遇到了与您相同的问题,我仍然不明白这个解决方案。你能解释一下它是如何工作的吗?它是如何解决你原来的问题的?谢谢。该解决方案之所以有效,是因为cx和cy的attr更新不在enter()上下文中,所以每次都会发生。在原始代码中,attr函数在enter()上下文中调用,因此根据对象标识只创建一次。它为我做的是学习关键函数作为data()的第二个参数:
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr("r", 2.5);
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circle.exit().remove();