简体   繁体   English

D3强制布局数据不更新

[英]D3 force layout data doesn't update

I'm using D3's forced layout graph to plot the data. 我正在使用D3的强制布局图来绘制数据。

  1. When I call the update function using setInterval with new data, the force layout graph nodes start from a random position. 当我使用带有新数据的setInterval调用update函数时,强制布局图节点从随机位置开始。 How can I fix this? 我怎样才能解决这个问题?
  2. The data is not getting updated even though console prints the correct data. 即使console打印正确的数据,数据也不会得到更新。 How can I solve this too? 我也该如何解决?

Here is the jsfiddle: https://jsfiddle.net/mootqvs1/ 这是jsfiddle: https ://jsfiddle.net/mootqvs1/

(Please avoid asking about different issues in the same question, specially when they are not related. Here I'll explain your problem #2, which is specific to your code. Your problem #1 is a general problem and has been already addressed in several questions/answers here at SO) (请避免在同一问题中询问不同的问题,特别是当它们不相关时。在这里,我将解释您的问题#2,它是特定于您的代码的。您的问题#1是一个普遍的问题,已经在中解决。在这里有几个问题/答案)

The problem with the update function is that you're using the indices as keys. 更新功能的问题是您将索引用作键。 However, the indices are the same for those different datasets! 但是,这些不同的数据集的索引是相同的!

Therefore, change this... 因此,请更改此...

if (!node.id) node.id = ++i;

... for something that assigns unique ids for the nodes. ...为节点分配唯一的 ID。 The obvious choice is using their names: 显而易见的选择是使用它们的名称:

if (!node.id) node.id = node.name;

However, even that won't work, because some nodes have the same name... so, we can mix the approaches: 但是,即使那样也行不通,因为某些节点具有相同的名称...因此,我们可以混合使用以下方法:

if (!node.id) node.id = node.name + (++i);

Have in mind that this is just an example. 请记住,这仅是示例。 The best solution is finding some property (or combination of properties) which are always unique and the same for each node. 最好的解决方案是找到一些属性(或属性组合),这些属性对于每个节点总是唯一且相同的。

Here is your code with that change only: 这只是您所做的更改的代码:

 var width = 680, height = 380, root; var data1 = { "name": "RootNode", "children": [{ "name": "B1", "children": [{ "name": "D1" }, { "name": "D2" }, { "name": "D3" }] }, { "name": "B2", "children": [{ "name": "D1" }, { "name": "D2" }, { "name": "D3" }, { "name": "D4" }] }, { "name": "B3", "children": [{ "name": "D1" }, { "name": "D2" }, { "name": "D3" }, { "name": "D4" }, { "name": "D5" }] }, { "name": "B4", "children": [{ "name": "D1" }, { "name": "D2" }, { "name": "D3" }, { "name": "D4" }] }, { "name": "B5", "children": [{ "name": "D1" }] }] }; var data2 = { "name": "Root", "children": [{ "name": "Box1", "children": [{ "name": "device1" }, { "name": "device2" }, { "name": "device3" }] }, { "name": "Box2", "children": [{ "name": "device1" }, { "name": "device2" }, { "name": "device3" }, { "name": "device4" }] }, { "name": "Box3", "children": [{ "name": "device1" }, { "name": "device2" }, { "name": "device3" }, { "name": "device4" }, { "name": "device5" }] }, { "name": "Box4", "children": [{ "name": "device1" }, { "name": "device2" }, { "name": "device3" }, { "name": "device4" }] }, { "name": "Box5", "children": [{ "name": "device1" }] }] }; var force = d3.layout.force() .linkDistance(80) .charge(-120) .gravity(.05) .size([width, height]) .on("tick", tick); var svg = d3.select(".network-graph").append("svg") .attr("width", width) .attr("height", height); var link = svg.selectAll(".link"), node = svg.selectAll(".node"); root = data1; update(); setInterval(function() { root = data2; update(); }, 5000); function update() { var nodes = flatten(root), links = d3.layout.tree().links(nodes); // Restart the force layout. force .nodes(nodes) .links(links) .start(); // Update links. link = link.data(links, function(d) { return d.target.id; }); link.exit().remove(); link.enter().insert("line", ".node") .attr("class", "link"); // Update nodes. node = node.data(nodes, function(d) { return d.id; }); node.exit().remove(); var nodeEnter = node.enter().append("g") .attr("class", "node") .on("click", click) .call(force.drag); nodeEnter.append("circle") .attr("r", function(d) { return 15 || 4.5; }); nodeEnter.append("text") .attr("dy", ".35em") .text(function(d) { return d.name; }); node.select("circle") .style("fill", color); } function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); } function color(d) { return d._children ? "#3182bd" // collapsed package : d.children ? "#c6dbef" // expanded package : "#fd8d3c"; // leaf node } // Toggle children on click. function click(d) { if (d3.event.defaultPrevented) return; // ignore drag if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(); } // Returns a list of all nodes under the root. function flatten(root) { var nodes = [], i = 0; function recurse(node) { if (node.children) node.children.forEach(recurse); if (!node.id) node.id = node.name + (++i); nodes.push(node); } recurse(root); return nodes; } 
 .node circle { cursor: pointer; stroke: #3182bd; stroke-width: 1.5px; } .node text { font: 10px sans-serif; pointer-events: none; text-anchor: middle; } line.link { fill: none; stroke: #9ecae1; stroke-width: 1.5px; } 
 <script src="https://d3js.org/d3.v3.min.js"></script> <div class="network-graph"></div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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