[英]Dynamically Clear and Update d3.js Force Directed Layout On Change
With the Mobile Patent Suit example by Mike Bostock as an example, I was able to re-create using my own data, but I want to take it a step further and dynamically update the node relationships on a drop-down change. 以Mike Bostock的“移动专利诉讼”示例为例,我能够使用自己的数据进行重新创建,但是我想更进一步,并在下拉更改中动态更新节点关系。 The code works almost every time, but occasionally I get a single node with no relationships (see image below) even though data are available. 该代码几乎每次都能工作,但是即使有可用数据,我偶尔也会得到一个没有关系的单个节点(请参见下图)。 I think I may be doing something wrong when clearing and then updating the nodes on a selection change, but it's strange to me that is works some of the time. 我认为清除和更新选择更改后的节点时可能做错了事,但是对我来说有时候会起作用是很奇怪的。 Any help is greatly appreciated. 任何帮助是极大的赞赏。
http://jsfiddle.net/calanoue/r6BRr/ http://jsfiddle.net/calanoue/r6BRr/
var selectedCode = '0';
function updateNodes() {
// Update the links and the nodes any time the data changes
svg.selectAll('g').remove();
links = allData[0][selectedCode];
// Compute the distinct nodes from the links.
links.forEach(function (link) {
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});
force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(80)
.charge(-400)
.on("tick", tick)
.start();
path = svg.append("g").selectAll("path")
.data(force.links())
.enter().append("path")
.attr("class", "link relationship")
.attr("marker-end", "url(#relationship)");
circle = svg.append("g").selectAll("circle")
.data(force.nodes())
.enter().append("circle")
.attr('class', "generic")
.attr("r", 8)
.call(force.drag);
}
function tick() {
// Use elliptical arc path segments to doubly-encode directionality.
path.attr("d", linkArc);
circle.attr("transform", transform);
}
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
function clearNodes() {
nodes = {};
links = [];
force.start();
d3.timer(force.resume);
}
function codeChange() {
selectedCode = this.value;
clearNodes();
updateNodes();
}
Missing Node Relationship Image: 缺少节点关系图像:
The problem you were having is that your original data, allData
, was being changed by the computation of links and nodes at each data change iteration. 您遇到的问题是,在每次数据更改迭代时,链接和节点的计算都会更改原始数据allData
。 After all, you set links = cloneData[0][selectedCode];
毕竟,您设置links = cloneData[0][selectedCode];
. 。 You need to clone allData
before each data change. 您需要在每次更改数据之前克隆allData
。
function codeChange() {
selectedCode = this.value;
cloneData = clone(allData); // added
clearNodes();
updateNodes();
}
Here is a FIDDLE with all the changes to make it work. 这是一个包含所有更改以使其工作的FIDDLE 。 I borrowed the clone function from this SO question . 我从这个SO问题中借用了克隆函数。
NOTE: I also removed one of your dropdown choices since you only have 3 sets of data in allData
. 注意:我也删除了您的下拉选项之一,因为allData
只有3套数据。 That was not the cause of your problems, per above, but it was throwing errors whenever you selected the inexistent set. 上面并不是那是造成问题的原因,但是每当您选择不存在的集合时,它就会引发错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.