如何在树形布局中将新节点推送到D3中的现有节点?

时间:2015-09-17 21:57:27

标签: d3.js tree

我已经尝试了this这个,它可以工作,但它取代了我的整个树,因为它位于节点的零索引处。

var newguys= jQuery.parseJSON(getLevel(2,'123456'));
var newnodes = tree.nodes(newguys).reverse();
d.children = newnodes[0];
update(d);

所以我尝试了推,

// Toggle children on click.

    function click(d) {
     var newguys= jQuery.parseJSON(getLevel(2,'123456'));
      if (d.children) {
        d._children = d.children;
        d.children = null;
      } else {
        d.children = d._children;
        d._children = null;
      }
    nodes.children.push(newguys);
       update(d);
    }

更新是d3的标准更新功能(我们假设我已经阅读了json)。我无法在父元素的末尾(或其他任何地方)获取新数据。

    var margin = {top: 20, right: 120, bottom: 20, left: 120},
        width = 960 - margin.right - margin.left,
        height = 1800 - margin.top - margin.bottom;

    var i = 0,
        duration = 750,
        root;

    var tree = d3.layout.tree()
        .size([height, width]);

    var diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.y, d.x]; });

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.right + margin.left)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");    

function update(source) {

  // Compute the new tree layout.

  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });

  // Update the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { 
        return d.id || (d.id = ++i); 


      });

  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
      .on("click", click);


  nodeEnter.append("circle")
      .attr("r", 1e-6)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeEnter.append("text")
      .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
      .text(function(d) { return d.name; })
      .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

  nodeUpdate.select("circle")
      .attr("r", 4.5)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeUpdate.select("text")
      .style("fill-opacity", 1);

  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
      .remove();

  nodeExit.select("circle")
      .attr("r", 1e-6);

  nodeExit.select("text")
      .style("fill-opacity", 1e-6);

  // Update the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", function(d) {
        var o = {x: source.x0, y: source.y0};
        return diagonal({source: o, target: o});
      });

  // Transition links to their new position.
  link.transition()
      .duration(duration)
      .attr("d", diagonal);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(duration)
      .attr("d", function(d) {
        var o = {x: source.x, y: source.y};
        return diagonal({source: o, target: o});
      })
      .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}

1 个答案:

答案 0 :(得分:0)

我不知道这是否是正确的方法,但这是我最后插入一个新节点所做的工作,代码是从我的所有旅行中修改的。我无法在任何地方找到它,所以我希望它可以帮到某人:

// Toggle children.
function toggle(d) {
    //works.
     var a; 
     if(d.children)
    {
        a={"name": "No More Records"};
        d.children.push(a);
    } else {
            d3.xhr(url)
            .header("X-Requested-With", "XMLHttpRequest")
            .header("Content-Type", "application/x-www-form-urlencoded")
            .post("level=1&emp="+d.empid, function (error, request) {
                if (error) return console.warn(error.responseText);
                var folks = jQuery.parseJSON(request.responseText);
                d.children = [folks];
                update_new(d);
            });
    }
}

我有update_new,因为我做了一些事情来使添加的子节点看起来不同,但更新与库存更新(d)功能基本相同。