使用NodeSize在节点之间进行D3树布局分离

时间:2013-07-09 21:32:36

标签: javascript tree d3.js

现在我正在尝试分离我的矩形节点,因为它们重叠,如下图所示:

enter image description here

我看一看,发现D3提供了nodeSizeseparation方法,但出于某种原因,它无效。

我发现这个blog post正在谈论这个问题,但他说

  

size属性在节点中不存在,因此它将是您想要控制它们大小的任何属性。

但显然有一个nodeSize方法,所以我觉得我只是错误地使用该方法和/或博客文章已过时。我想将我的节点整形为矩形的大小并将它们均匀分开,这样它们就不会相互重叠。有谁知道如何正确使用这些方法?关于这些方法的文档没有得到很好的解释,并没有产生任何差别。我也找不到很多例子,人们改变了树的nodeSize或需要分离矩形对象(有一些关于圆形对象的例子,但我觉得这太不同了......)

这是相关代码。我将尝试准备一个JSFiddle。

var margin = {top: 20, right: 120, bottom: 20, left: 120},
    height = 960 - margin.right - margin.left,
    width = 800 - margin.top - margin.bottom,
    rectW = 70;
    rectH = 30;
    //bbox = NaN,
    maxTextLength = 0;

var i = 0,
    duration = 750,
    root;


//paths from each node drawn initially here
//changed to d.x, d.y
var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x+rectW/2, d.y+rectH/2];
    //.projection(function(d) { return [d.x+bbox.getBBox().width/2, d.y+bbox.getBBox().height/2]; 
});

var tree = d3.layout.tree()
    .nodeSize([30,70])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2); })
    .size([width, height]);

var svg = d3.select("body")
            .append("svg")
              .attr("height","100%").attr("width","100%")
              .call(d3.behavior.zoom().on("zoom", redraw))
              .append("g")
                .attr("transform", "translate(" + margin.top + "," + margin.left + ")");

4 个答案:

答案 0 :(得分:43)

更新05/04/2018 :据我所知,d3已经改变了很多(为了更好)更加模块化。对于那些正在寻找这个答案的人来说,这是使用更老版本的d3(特别是v3)。

许多调查结果仍与d3-hierarchy下的cluster.size() and cluster.nodeSize()包相关,我计划更新我的示例以使用它。但是,作为历史参考,我没有触及底部。


这是一个jsFiddle:http://jsfiddle.net/augburto/YMa2y/

编辑:更新并将示例移至Codepen。这个例子仍然存在于jsFiddle中,但Codepen似乎有一个更好的编辑器,并允许您轻松分叉。一旦我减少了内容的数量,我还会尝试将示例直接添加到此答案中。

http://codepen.io/augbog/pen/LEXZKK

更新此答案。我和我的朋友谈过,我们查看了sizenodeSize

的来源
  tree.size = function(x) {
    if (!arguments.length) return nodeSize ? null : size;
    nodeSize = (size = x) == null;
    return tree;
  };

  tree.nodeSize = function(x) {
    if (!arguments.length) return nodeSize ? size : null;
    nodeSize = (size = x) != null;
    return tree;
  };

为树设置size时,您将设置固定大小,以使树必须符合该宽度和高度。设置nodeSize时,树必须是动态的,因此它会重置树的大小。

当我在size之后指定nodeSize时,我几乎压倒了我想要的东西哈哈......

底线:如果您希望nodeSize正常工作,则无法使用固定的树大小。它会将大小设置为null。如果您要声明size,请不要声明nodeSize

编辑:D3.js实际上updated the documentation。感谢无论谁做到了,因为它现在更清晰了!

  

nodeSize属性与tree.size不同;设置   tree.nodeSize将tree.size设置为null。

这就是我的树现在的样子。我还添加了缩放功能以及如何在矩形中居中文本。

Picture where nodeSize is set at width of 100 and height of 30

答案 1 :(得分:11)

在我对自己进行挖掘之前,我不太明白接受的答案,所以我想我也会分享我发现的......

如果您使用.size()且节点重叠,请使用.nodeSize()代替

如接受的答案所述,.size()设置了树的可用大小,因此根据堂兄节点,第二堂兄弟等之间的间距,它们可能会被挤压在一起并重叠。使用.nodeSize()只是说每个节点都应该占用这么多空间,所以它们永远不会重叠!

最终为我工作的代码是

var nodeWidth = 300;
var nodeHeight = 75;
var horizontalSeparationBetweenNodes = 16;
var verticalSeparationBetweenNodes = 128;

var tree = d3.layout.tree()
    .nodeSize([nodeWidth + horizontalSeparationBetweenNodes, nodeHeight + verticalSeparationBetweenNodes])
    .separation(function(a, b) {
        return a.parent == b.parent ? 1 : 1.25;
    });

没有horizontalSeparationBetweenNodesverticalSeparationBetweenNodes,节点边缘相互接触。我还添加了这个.separation()来减少表兄节点之间的空间量,因为我的节点非常宽,并且浪费了大量空间。

注意:这适用于d3 v3,而不是v4

答案 2 :(得分:0)

首先,感谢所有发布过的人,纯金。 我想为那些可能正在努力解决与水平绘制树相关的偏移问题的人添加这篇文章。

关键是,如果你在水平树上从.size()切换到.nodeSize(),你会注意到你的根节点似乎跳转/重定向位于(0,0)。 根据d3.js文档,实际情况就是这样(见https://github.com/d3/d3-hierarchy/blob/master/README.md#tree_nodeSize

但是,要调整您,只需确保重定向viewBox。 也就是说,当您.append svg时,您需要明确设置viewBox。这是我的hacky小行,它对我有用......

svg = d3.select("#tree").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + 0 + 0)
            .attr("viewBox", "0 "+(-1*(height-margin.top-margin.bottom)/2)+" "+width+" "+height)
            .append("g")
            .attr("transform", "translate("
                  + margin.left + "," + 0 + ")");

答案 3 :(得分:-1)

D3现在通过 Observable 执行操作。

设置 nodeSize ,请找到

main.variable(observer("tree")).define("tree", ["d3","dx","dy"],
function(d3,dx,dy){return(
d3.tree()

使用添加的常量设置nodeSize

main.variable(observer("tree")).define("tree", ["d3","dx","dy"],
function(d3,dx,dy){return(
d3.tree().nodeSize([dx + 10, dy + 10])

或者使用其他D3方法使用函数来设置图表大小的值,如其他答案中所述。