将节点添加到树力布局 - 几乎可以正常工作

adding nodes to tree force layout - almost working

我正在使用强制布局和树层次结构。

它几乎可以工作并添加节点和链接,但它们不可见。 可能我遗漏了一些微不足道的东西,但我在这上面花了太多时间...... 非常感谢任何帮助。

在此模型中,单击后,应将第三个节点添加到根。

var width = 960,
    height = 500,
    root;

var force = d3.layout.force()
   .linkDistance(80)
    .charge(-320)
    .gravity(0.05)
    .size([width, height])
    .on("tick", tick);

var svg = d3.select("#myviz").append("svg")
    .attr("width", width)
    .attr("height", height);

var link = svg.selectAll(".link"),
    node = svg.selectAll(".node");

var mydata = '{ "name": "start_bubble", "children": [  {   "name":     "child_O1", "size": 31812},{   "name": "child_O2", "size": 31812}]}';
var myadd = '{"name": "new_child", "size": 100}';

root = JSON.parse( mydata); 
myaddparsed = JSON.parse( myadd); 

update();
force.start();

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")

    .style("stroke-width",2)
    .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 Math.sqrt(d.size) / 5 || 14.5; });

  nodeEnter.append("text")
      .attr("dy", "2.3em")
    .text(function(d) { return d.name; });

  node.select("circle")
      .style("fill", color);
  force.start();
}

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(" + d.x + "," + d.y + ")"; });
}

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; remove for testing
    //    d.children = null; removed for testing

root.children[2]=myaddparsed; //add third node

  } else {
    //    d.children = d._children; removed for tesing
    //    d._children = null;  removed for testing

root.children[2]=myaddparsed; //add third node

  }
  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 = ++i;
    nodes.push(node);
  }

  recurse(root);
   return nodes;
}

http://jsfiddle.net/jo636df/o81xxmjm/

You come to Whosebug, and you say: "I index my data with the value of i incremented in recurse." But you don't maintain the value between calls to flatten. You don't offer uniqueness. You don't even think to tell D3 that you have new data. Instead, you reset i to 0, immediately increment it by one with ++i, set it on your new element and you ask D3 to figure out that your new element is indeed new when you already have another element with id equal to 1.

您需要确保您的 id 确实是独一无二的。作为快速修复,您可以将 i 拉到外部上下文以避免将其重置为零。这是一个 fiddle.