在D3树中添加动态节点

时间:2016-01-14 09:49:33

标签: javascript d3.js

我正在学习d3 js布局,并且难以将节点添加到树布局中。

希望在单击父节点后添加动态节点(子节点)。

我当前的实现确实添加了节点,但它不是更新节点,而是添加了新的子节点并保留了之前的子节点。

有人可以帮助我理解这个问题以及解决问题的正确方法。

这是我的代码和我的Fiddle(点击根节点):

HTML

<div id="body"> 
</div>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>

JS

var margin = {top: 100, right: 50, bottom: 100, left: 50},
    width = 900 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;


var tree = d3.layout.tree()
    .separation(function(a, b) { return a.children === b.children ? 1 : 1.2; })
    .size([width, height]); 

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

var dataOne = {
  "name": "Mike and Marcia",
  "children": [
    {
      "name": "Children",
      "children": [
        { "name": "Mikael" }
      ]
    }
  ]
};

var drawTree = function(source){

 var nodes = tree.nodes(source);
 var node = svg.selectAll(".node")
    .data(nodes)
    .enter()
    .append("g");

 var boxes = node.selectAll('g')
            .data(nodes)
            .enter()
            .append('g')
            .append('rect')
            .attr("width", 50)
            .attr("height", 40)
            .attr("fill", "tan")
            .attr("x", function(d) { return d.x; })
            .attr("y", function(d) { return d.y + 50; });


  boxes.on("click", function(d,i){
   clickOutside(d);
  });


};

var clickOutside = function(value){
  var newData = {
        "name": "Mike and Marcia",
        "children": [{
            "name": "Children",
            "children": [{
                "name": "Mikael"
            }]
        },{
            "name": "Pets",
            "children": []
        }]
     };

 drawTree(newData);    
 console.log(value);

}

drawTree(dataOne);

1 个答案:

答案 0 :(得分:1)

问题在于您是在旧图表上绘制新图表。

这就是为什么你会得到它将孩子添加到旧父母的印象的原因。

所以正确的方法是

  1. 绘制图表
  2. 删除所有不需要的节点。
  3. 所以第1点

     var nodedata = svg.selectAll(".node")
        .data(nodes, function(d){ /* function which return the Unique id of each node */ return d.name;})
    
        //make all the nodes.
        nodedata.enter().append('g')
                .attr("class", "node")
                .append('rect')
                .attr("width", 50)
                .attr("height", 40)
                .attr("fill", "tan")
                .attr("x", function(d) { return d.x; })
                .attr("y", function(d) { return d.y + 50; })
                .on("click", function(d,i){
                 clickOutside(d);
                });
    

    第二点

    删除与第一组传递数据和第二组传递数据相交的所有节点。

    nodedata.exit().remove();
    

    最后一点将儿童添加到父级

    您可以更改JSON

    var dataOne = {
      "name": "Mike and Marcia",
      "children": [
        {
          "name": "Children",
          "children": [
            { "name": "Mikael" }
          ]
        }
      ]
    };
    

    添加任何结构JSON并将其传递给drawTree function

    工作代码here