D3树垂直分离

时间:2012-10-23 14:27:16

标签: javascript tree d3.js

我正在使用D3树格式,例如:http://mbostock.github.com/d3/talk/20111018/tree.html

我已根据自己的需要对其进行了修改,但遇到了问题。该示例也存在相同的问题,如果您打开了太多节点,那么它们会变得紧凑并使阅读和交互变得困难。我想在重新调整阶段以确定节点之间的最小垂直空间以允许这样的间距。

我尝试修改分离算法以使其工作:

.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);

我也尝试在下面的方法中更改节点的x值,它计算y分离,但没有雪茄。我也会发布这个更改,但是我从代码中删除了它。

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

如果您可以建议某种方式或知道我可以在节点之间垂直实现最小间距的方法,请发布。我将非常感激。我可能错过了很简单的事情。

4 个答案:

答案 0 :(得分:5)

截至2016年,我只用

就能实现这一目标
tree.nodeSize([height, width])

https://github.com/mbostock/d3/wiki/Tree-Layout#nodeSize

API参考有点差,但是非常直接。请务必在tree.size([height, width])之后使用它,否则您将再次覆盖您的值。

更多参考:D3 Tree Layout Separation Between Nodes using NodeSize

答案 1 :(得分: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 :(得分:2)

我知道我不应该回答其他答案,但我没有足够的声誉来添加评论。

无论如何,我只想为使用最新d3.v3.js文件的人更新此内容。 (我认为这是因为新版本,因为接受的答案中的行引用对我来说是错误的。)

您正在编辑的d3.layout.tree函数位于第6236行和第6345行之间.d3_layout_treeVisitAfter从第6318行开始。层次结构变量在第6237行声明。关于tree.elementsize的位仍然有效 - 我把它放在6343行。

最后(我假设这是一个错误):当您创建树时,将尺寸放在方括号内,就像通常使用“尺寸”一样。所以:

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

答案 3 :(得分:0)

您提出的原始修复程序将起作用,您必须确保在将所有内容添加到画布后执行此操作。 d3每次进入,退出,追加等时都会重新计算布局。一旦完成了所有这些操作,就可以使用d.y来修正深度。

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