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

qzlgjiam  于 9个月前  发布在  Java
关注(0)|答案(5)|浏览(204)

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


的数据
我看了一下,发现D3提供了一个nodeSize和分离方法,但由于某种原因,它不起作用。
我发现这个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 + ")");

字符串

np8igboo

np8igboo1#

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

很多发现仍然与cluster.size()cluster.nodeSize()下的d3-hierarchy包相关,我计划可能更新我的示例以使用它。
下面是一个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时,树必须是动态的,所以它重置了树的大小。
当我在nodeSize之后指定size时,我几乎覆盖了我想要的东西哈哈。

底线:如果你想让nodeSize工作,你不能有一个固定的树大小。它会将大小设置为null。如果你正在声明一个nodeSize,不要声明一个size
编辑:D3.js实际上更新了文档。感谢做这件事的人,因为它现在更清晰了!

nodeSize属性与tree.size互斥;设置tree.nodeSize会将tree.size设置为null。
这就是我的树现在的样子。我还添加了缩放功能以及如何在矩形内居中文本。
x1c 0d1x的数据

4ioopgfo

4ioopgfo2#

直到我自己做了一些挖掘,我才完全理解了公认的答案,所以我想我也会分享我的发现。

如果您使用的是.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*
pwuypxnk

pwuypxnk3#

首先,感谢所有以前发帖的人,纯金。我想为那些可能正在与水平绘制的树相关的偏移问题作斗争的人补充这篇文章。
关键是,如果你在一个水平树上从.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 + ")");

字符串

92vpleto

92vpleto4#

如果有人正在使用react-d3-tree并希望在节点之间添加margin,您可以添加:

<Tree
                nodeSize={{ x: 250, y: 200 }}
                ...
/>

字符串
并调整值以满足您的要求:)

9wbgstp7

9wbgstp75#

D3现在通过**Observable**执行操作。

设置*nodeSize**look:

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

字符串
然后set nodeSize with added constants

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


或者使用一个函数来设置图表大小的值,就像在其他答案中使用旧的D3方法所讨论的那样。

相关问题