2016-01-14 99 views
1

我学习了d3 js布局,并且难以向树布局添加节点。在D3树中添加动态节点

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

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

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

这里是我的代码和我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

的问题是,你在绘制新图旧图。

这就是为什么你会得到一个印象,那就是它将孩子添加到老父母身上。

所以,正确的做法是

  1. 绘制图形
  2. 删除不需要的所有节点。

所以第一点

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

+1

非常感谢你的简短而全面的解释@Cyril。这正是我想让它工作的原因。我确实有跟进问题以进一步了解d3概念。如果我将问题指向你,可以吗? – diehell