【问题标题】:Children with n>1 parents in d3.js tree layoutd3.js 树布局中具有 n>1 个父母的孩子
【发布时间】:2015-10-02 14:16:59
【问题描述】:

d3.js 树形布局是一个很棒的工具,但默认情况下它只允许子级有一个父级。我希望能够让孩子有不止一个父母。我对树的默认行为提供的节点位置感到满意。我想要的只是在计算出默认树之后,在没有孩子的父母和现有的孩子之间绘制额外的对角线链接。 我的脚本目前看起来像这样:

<script>

var h = 870,
    w = 1200;
var dimcirc = [60,30,10,8];
var offsetL = 60;
var couleurs = [
        "#a2a2ff",
        "#87ff87",
        "#ffc55c",
        "#ff844d",
        "#ffe452"];

var tree = d3.layout.tree()
    .size([h-100, w-400])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 1.2); });

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y + offsetL, d.x]; });

var svg = d3.select("body").append("svg")
    .attr("width", w)
    .attr("height", h)
  .append("g");

d3.json("donnees.json", function(error, root) {
  if (error) throw error;

  var nodes = tree.nodes(root),
      links = tree.links(nodes);

  var link = svg.selectAll(".link")
    .data(links)
    .enter().append("path")
    .attr("class", "link")
    .attr("d", diagonal);

  var node = svg.selectAll(".node")
    .data(nodes)
    .enter().append("g")
    .attr("class", function(d){return "niv_" + d.depth.toString();})
    .classed("node", true)
    .attr("transform", function(d) { return "translate(" + (d.y + offsetL).toString() +  "," + d.x +")"; })

  // Draw node circles
  node.append("circle")
        .attr("fill", function(d){
                console.log(d.couleur);
                if(d.couleur!=null){
                    return couleurs[d.couleur];
                }
                else {return couleurs[4];}
        })
      .attr("r", function(d){
        return dimcirc[d.depth];   
  });

  node.append("text")
      .attr("dy", "0.31em")
      //.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d){
            return "translate(" + (dimcirc[d.depth] + 10).toString() + ")"
            })
      .text(function(d) { return d.name; })
        .call(wrap, 230);

});

// Wrap text
function wrap(text, width) {
   // A function to help wrap svg text.
}

</script>

我尝试使用根对象将父节点的子节点复制到无子节点,但无济于事(根对象的结构对我来说非常模糊)。

任何帮助表示赞赏。

PS :我知道一个类似的问题 (d3.js tree nodes with same parents),但没有答案对我没有太大帮助。

编辑

我已经设法得到了我想要的东西:

1) 识别感兴趣的节点:那些没有子节点的节点将连接到现有子节点,以及后者的父节点。

2) 从根对象中提取源(没有子节点的节点)和目标(要连接到该节点的子节点)的坐标。

3) 使用与树创建的“标准”路径相同的对角线创建额外路径。

这是我添加的用于获取每个路径的源和目标的代码:

var link2 = [];
var loopLink2 = [{"a":0,"b":1, "c":0,"d":0},{"a":1,"b":1, "c":1,"d":0},{"a":3,"b":0, "c":2,"d":1}];

loopLink2.forEach(function(d){

    var sourX = root.children[d.a].children[d.b].x;
    var sourY = root.children[d.a].children[d.b].y;

    root.children[d.c].children[d.d].children.forEach(function(d){
        link2.push({"source":{"x":sourX,"y":sourY}, "target":{"x":d.x,"y":d.y}});
        console.log(link2);
    });
});

这里是路径的实际创建位置:

svg.selectAll(".link2")
    .data(link2)
    .enter().append("path")
    .attr("class", "link2")
    .attr("d", diagonal)
    .attr("transform", function(d) { return "translate(0," + offsetT +")"; });

有人有更好的解决方案吗?

【问题讨论】:

  • 节点有多个父节点的图不再是一棵树。我认为树形布局在这里不是正确的选择;也许是力布局?

标签: javascript d3.js tree


【解决方案1】:

我不知道这是否正是您想要的。但这可能会有所帮助。

Dagre

Dagre 是一个使用 d3 绘制非循环图的库。您可以尝试修改它。 Here 是 github wiki。

家谱

Here 您可以找到创建家谱的绝佳答案,一个孩子可以有多个父母。如果结构无关紧要,这可能会满足您的要求。

【讨论】:

  • 感谢您指出这些。正如我在编辑中所解释的那样,我已经设法解决了我的问题。
猜你喜欢
  • 2017-09-17
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2019-11-24
相关资源
最近更新 更多