Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
423 views
in Technique[技术] by (71.8m points)

javascript - Dynamically resize the d3 tree layout based on number of childnodes

From this example http://mbostock.github.com/d3/talk/20111018/tree.html I have build a d3 tree layout where the root is in the middle(root.x0 = width/2) in the browser window and the nodes are in the downward direction instead of facing to the right.

Is it possible to re-size the tree, such that the width of the tree is dependent on the number of nodes of the tree such that if number of nodes is less, then width is less or else if number of nodes is greater then width is large ?

I also need to know how d3 tree layout currently calculates the "d.x" attribute? How can I manipulate "d.x" attribute to adjust the spacing between the nodes of the d3 tree layout.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So when you set the "size" of the tree layout all you are doing is setting the value the tree layout will interpolate the x and y values to. So there is no reason you can't compute the width or height you want and change it in the layout on each update call.

I copied the example you gave to a jsFiddle and added the following to the update function:

// compute the new height
var levelWidth = [1];
var childCount = function(level, n) {

  if(n.children && n.children.length > 0) {
    if(levelWidth.length <= level + 1) levelWidth.push(0);

    levelWidth[level+1] += n.children.length;
    n.children.forEach(function(d) {
      childCount(level + 1, d);
    });
  }
};
childCount(0, root);  
var newHeight = d3.max(levelWidth) * 20; // 20 pixels per line  
tree = tree.size([newHeight, w]);

Note that this is a pretty rough calculation and does not factor in where the children are w.r.t their parents or anything - but you get the idea.

As for manipulating the x values of the nodes the easiest is probably to simply modify the nodes after the layout has done it's thing. In fact you can see that this is already done in the example with the y coordinate:

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

He does this so that even if children are hidden a given level of nodes stays at the same y position, otherwise if you collapsed all the children the remaining levels would stretch to take up the whole width (try commenting that line out and see what happens as you toggle whole levels invisible).

As for going top down I think you can pretty much just flip everywhere you see x and y (and x0 and y0). Don't forget to do the same to the diagonal projection to make sure your lines flip too.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...