避免d3.js中树布局中的节点重叠

时间:2014-01-01 15:53:41

标签: d3.js tree nodes hierarchy

我创建了一个可折叠的树来代表一些生物数据。

在此树中,节点的大小表示节点的重要性。由于我拥有庞大的数据,并且节点的大小也各不相同,因此它们相互重叠。我需要指定兄弟节点之间的距离。

我尝试了tree.separation()方法,但它没有用。

代码如下:

tree.separation(seperator);

function seperator(a, b)
{
    if(a.parent == b.parent)
    {
        if((a.abundance == (maxAbd)) || (b.abundance == (maxAbd)))
        {
            return 2;
        }
        else
        {
            return 1;
        }
    }
}

这让我错误地说:

Unexpected value translate(433.33333333333337,NaN) parsing transform attribute.

据我所知,添加分离方法后,无法计算节点的x坐标。任何人都可以帮我解决这个问题吗?

我也尝试按https://groups.google.com/forum/#!topic/d3-js/7Js0dGrnyek中的建议修改源代码,但这也不起作用。

请提出一些解决方案。

2 个答案:

答案 0 :(得分:5)

我遇到了同样的问题。这就是我解决它的方式。我为每个节点分配了宽度,现在的高度对于所有节点都是相同的(基本上高度小于nodeHeight的节点,垂直居中):

var tree = d3.layout.tree().nodeSize([1, nodeHeight])
           .separation(function(a, b) {
               var width = a.width + b.width,
                   distance = width / 2 + 16; // horizontal distance between nodes = 16
                   return distance;
           }),
    nodes = tree.nodes(data),
    links = tree.links(nodes);

希望这有帮助。

答案 1 :(得分:3)

SiegS的回答运作正常!

我的情况是:我的节点实际上是一些文本,可能有不同的宽度,我事先并不知道。所以我需要先计算每个节点的宽度。

我有一个JSON对象json_data作为我的数据。

var tree = d3.layout.tree()
.sort(null)
.size([500,500])
.children( some_function_identify_children );

var nodes = tree.nodes(json_data); //which doesn't consider the node's size;
var links = tree.links(nodes);

// append a svg;
var layoutRoot = d3.select("body")
.append("svg:svg").attr("width","600").attr("height","600")
.append("svg:g")
.attr("class","container");

var nodeGroup = layoutRoot.selectAll("g.node")
.data(nodes)
.enter().append("text").text(function(d){return d.text;});
// now we knows the text of each node. 

//calculate each nodes's width by getBBox();
nodeGroup.each(function(d,i){d["width"] = this.getBBox().width;})

//set up a new tree layout which consider the node width. 
var newtree = d3.layout.tree()
.size([500,500])
.children(function(d) {return d.children;})
.separation(function(a,b){
  return (a.width+b.width)/2+2;
});

//recalcuate the node's x and y by newtree
newtree.nodes(nodes[0]); //nodes[0] is the root
links = newtree.links(nodes);

//redraw the svg using new nodes and links.
...

希望这会有所帮助。