简体   繁体   English

动态清除和更新d3.js强制更改时定向的布局

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM