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 +")"; });
有人有更好的解决方案吗?