D3树垂直分离
Posted
技术标签:
【中文标题】D3树垂直分离【英文标题】:D3 tree vertical separation 【发布时间】:2012-10-23 14:27:15 【问题描述】:我用的是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);
我还尝试在下面计算y
分离但没有雪茄的方法中更改节点的x
值。我也会发布该更改,但我将其从我的代码中删除。
nodes.forEach(function(d, i)
d.y = d.depth * 180;
);
如果您可以提出一种方法或知道一种方法,我可以在节点之间垂直实现最小间距,请发布。我将不胜感激。我可能遗漏了一些非常简单的东西。
【问题讨论】:
【参考方案1】:截至 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
【讨论】:
【参考方案2】:在 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);
【讨论】:
这里是 Google 网上论坛链接以获取更多信息groups.google.com/forum/?fromgroups#!topic/d3-js/7Js0dGrnyek 在 d3 版本 3 中,现在有一个 nodeSize 属性,它将与上述修改执行相同的操作。参考:github.com/mbostock/d3/wiki/Tree-Layout#nodeSize【参考方案3】:我知道我不应该回复其他答案,但我没有足够的声誉来添加评论。
无论如何,我只是想为使用最新 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,则不必进行修改。已经有一个 nodeSize 属性可以用来代替 elementize。【参考方案4】:您建议的原始修复将起作用,您只需确保在将所有内容添加到画布后执行此操作。 d3 会在您每次进入、退出、追加等时重新计算布局。完成所有这些后,您就可以调整 d.y 来修复深度。
nodes.forEach(function(d) d.y = d.depth * fixdepth);
【讨论】:
以上是关于D3树垂直分离的主要内容,如果未能解决你的问题,请参考以下文章