D3 树布局 - 当孩子超过一定数量时自定义垂直布局 [英] D3 Tree Layout - Custom Vertical Layout when children exceed more than a certain number

查看:34
本文介绍了D3 树布局 - 当孩子超过一定数量时自定义垂直布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 D3 树布局来创建各种家谱,我注意到的一件事是当我有很多子节点时,它会在屏幕上水平延伸.理想情况下,我希望这些节点采用更垂直的布局,这样人们就不必在屏幕上滚动,而可以继续向下看树.

这是我目前看到的:

现在可能没那么糟糕,但如果我说有 20 个孩子,它会跨越整个屏幕,这是我想要避免的.

我见过类似 他说他必须玩弄实际的 d3js 代码.我有点想避免这种情况,所以我希望了解 d3js 是否可以像现在这样,如果可以,该怎么做?我不需要完整的答案,但是证明这是可能的一段代码会非常有帮助.

如有必要,我可以上传一个 JSFiddle 供人们玩.

解决方案

看看这个小提琴:

http://jsfiddle.net/dyXzu/

我从 http://bl.ocks.org/mbostock/4339083 并做了一些修改.请注意,在示例中,绘制时 x 和 y 切换,因此布局显示为垂直树.

我所做的重要事情是修改深度计算器:

原文:

//归一化固定深度.node.forEach(function(d) { d.y = d.depth * 180; });

修正:

//归一化固定深度.节点.forEach(函数(d){d.y = d.depth * 180;如果(d.parent != null){d.x = d.parent.x - (d.parent.children.length-1)*30/2+ (d.parent.children.indexOf(d))*30;}//如果节点有太多子节点,进入并将它们的位置固定为两列.如果(d.children != null && d.children.length > 4){d.children.forEach(function (d, i) {d.y = (d.depth * 180 + i % 2 * 100);d.x = d.parent.x - (d.parent.children.length-1)*30/4+ (d.parent.children.indexOf(d))*30/2 - i % 2 * 15;});}});

基本上,我手动计算每个节点的位置,覆盖 d3 的默认节点定位.请注意,现在 x 没有自动缩放.您可以通过首先遍历并计算打开的节点(如果存在,d.children 不为空,d._children 在节点关闭时存储节点),然后将总 x 相加,手动计算出这一点.

在两列布局中带有子节点的节点看起来有点古怪,但改变画线方法应该会有所改善.

I'm trying to use the D3 Tree Layout to create a family tree of sorts and one of the things I noticed is that when I have many children nodes, it would stretch out horizontally across the screen. Ideally I would like a more vertical layout for these nodes so that people don't have to scroll across the screen and can just keep looking down the tree.

Here is what I currently see:

Now it might not be that bad, but if I had say 20 children, it would span across the whole screen and that is something I kind of want to avoid.

I have seen questions like this but this doesn't help me because I want a specific layout and not simply a resize... I have large nodes and they begin to collide with one another if I try to dynamically resize the tree -- shrinking the tree does not do me any good. I specifically need a different layout for situations where there are more than a certain number of children.

Here is kind of what I was envisioning/hoping for. Notice the root does not make this format because it has only 4 children. Ideally I want it so that if a parent has 5 or more children, it would result in the layout below. If the root had 5 children, it would result in this layout and the layout should simply stretch out vertically if users wanted to see the root's grandchildren (the A, B, C... nodes). If necessary I can get a diagram of that going:

I found a semi-similar question regarding custom children layouts and he said he had to play around with the actual d3js code. I kind of want to avoid this so I am hoping to find out if this is possible with d3js as it is right now and, if so, how to go about it? I don't need a complete answer, but a snippet of code proving that this is possible would be very helpful.

If necessary I can upload a JSFiddle for people to play around with.

解决方案

Check out this fiddle:

http://jsfiddle.net/dyXzu/

I took the sample code from http://bl.ocks.org/mbostock/4339083 and made some modifications. Note that in the example, x and y are switched when drawing so the layout appears as a vertical tree.

The important thing I did was modifying the depth calculator:

Original:

// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });

Fixed:

// Normalize for fixed-depth.
nodes.forEach(function (d) {
    d.y = d.depth * 180;
    if (d.parent != null) {
        d.x =  d.parent.x - (d.parent.children.length-1)*30/2
        + (d.parent.children.indexOf(d))*30;
    }
    // if the node has too many children, go in and fix their positions to two columns.
    if (d.children != null && d.children.length > 4) {
        d.children.forEach(function (d, i) {
            d.y = (d.depth * 180 + i % 2 * 100);
            d.x =  d.parent.x - (d.parent.children.length-1)*30/4
            + (d.parent.children.indexOf(d))*30/2 - i % 2 * 15;
        });
    }
});

Basically, I manually calculate the position of each node, overriding d3's default node positioning. Note that now there's no auto-scaling for x. You could probably figure this out manually by first going through and counting open nodes (d.children is not null if they exist, d._children stores the nodes when they are closed), and then adding up the total x.

Nodes with children in the two-column layout look a little funky, but changing the line-drawing method should improve things.

这篇关于D3 树布局 - 当孩子超过一定数量时自定义垂直布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆