2012-10-23 63 views
10

我使用的是D3樹佈局,比如這一個:http://mbostock.github.com/d3/talk/20111018/tree.htmlD3樹垂直間隔

我已經修改了它適合我的需要和正在運行到一個問題。這個例子也有同樣的問題,如果你有太多的節點打開,那麼它們變得緊湊,使閱讀和交互變得困難。我想在定義節點之間的最小垂直空間的同時重新調整舞臺大小以允許這樣的間距。

我試圖修改分離算法,使其工作:

.separation(function (a, b) { 
    return (a.parent == b.parent ? 1 : 2)/a.depth; 
}) 

這沒有奏效。我也嘗試計算哪個深度的孩子最多,然後告訴舞臺的高度爲children * spaceBetweenNodes。這讓我更接近,但仍然不準確。

depthCounts = []; 
nodes.forEach(function(d, i) { 
    d.y = d.depth * 180; 

    if(!depthCounts[d.depth]) 
     depthCounts[d.depth] = 0; 

    if(d.children) 
    { 
     depthCounts[d.depth] += d.children.length; 
    } 
}); 

tree_resize(largest_depth(depthCounts) * spaceBetweenNodes); 

我也試圖在下面它計算y分離的方法也改變節點的x價值,但沒有雪茄。我也會發布這個改變,但是我把它從我的代碼中移除了。

nodes.forEach(function(d, i) { 
    d.y = d.depth * 180; 
}); 

如果你能提出一個方法或知道一個辦法,我可以做到垂直節點請張貼之間的最小間距。我將非常感激。我可能錯過了一些非常簡單的事情。

回答

4

我可以在Google網上論壇的用戶幫助下計算出來。我無法找到帖子。該解決方案要求您在一個地方修改D3.js,這是不推薦的,但它是解決此問題的唯一方法,我可以找到。

開始圍繞線5724或此方法:d3_layout_treeVisitAfter

變化:

d3_layout_treeVisitAfter(root, function(node) { 
    node.x = (node.x - x0)/(x1 - x0) * size[0]; 
    node.y = node.depth/y1 * size[1]; 
    delete node._tree; 
}); 

到:

d3_layout_treeVisitAfter(root, function(node) { 
    // make sure size is null, we will make it null when we create the tree 
    if(size === undefined || size == null) 
    { 
     node.x = (node.x - x0) * elementsize[0]; 
     node.y = node.depth * elementsize[1]; 
    } 
    else 
    { 
     node.x = (node.x - x0)/(x1 - x0) * size[0]; 
     node.y = node.depth/y1 * size[1]; 
    } 
    delete node._tree; 
}); 

下面添加一個名爲新變量:elementsize和默認它到[ 1, 1 ]到5731行

var hierarchy = d3.layout.hierarchy().sort(null).value(null) 
    , separation = d3_layout_treeSeparation 
    , elementsize = [ 1, 1 ] // Right here 
    , size = [ 1, 1 ]; 

下面有一個叫做tree.size = function(x)的方法。添加下面這個定義如下:

tree.elementsize = function(x) { 
    if (!arguments.length) return elementsize; 
    elementsize = x; 
    return tree; 
}; 

最後,當您創建樹可以改變elementsize像這樣

var tree = d3.layout.tree() 
      .size(null) 
      .elementsize(50, 240); 
+2

這裏是谷歌論壇鏈接瞭解更多信息https://groups.google.com/forum/?fromgroups#!topic/d3-js/7Js0dGrnyek – Biovisualize

+1

在D3版本3,現在有一個nodeSize屬性可以完成與上述修改相同的功能。參考:https://github.com/mbostock/d3/wiki/Tree-Layout#nodeSize – patorjk

0

您提出的將工作原來修復,你只需要確保你做它將所有內容添加到畫布後。每次你進入,退出,追加等等,d3都會重新計算佈局。一旦你完成了所有的工作,你就可以用d.y來調整深度。

nodes.forEach(function(d) { d.y = d.depth * fixdepth}); 
2

我知道我不應該回應其他答案,但我沒有足夠的聲望來添加評論。

無論如何,我只是想爲使用最新的d3.v3.js文件的人更新這個。 (我認爲這是因爲新版本,因爲接受的答案中的行引用對我來說是錯誤的。)

您正在編輯的d3.layout.tree函數位於第6236行和第6345行之間。d3_layout_treeVisitAfter啓動這個層次結構變量是在6237行聲明的。關於tree.elementsize的位仍然存在 - 我把它放在第6343行。

最後(我認爲這是一個錯誤):當你創建樹時,put方括號內的尺寸,就像你通常用「size」做的那樣。所以:

var tree = d3.layout.tree() 
     .size(null) 
     .elementsize([50, 240]); 
+0

如果您使用的是第3版,則不必進行修改。已經有一個nodeSize屬性可以用來代替元素大小。 – patorjk