几个月前,我尝试了combining Hierarchical Edge Bundling and Radial Reingold–Tilford Tree using d3.js
我从HEB开始尝试将它变成一棵树。 事情并没有按照我想要的方式解决,我意识到从一个可折叠的径向树(不是Reingold Tilford)开始,可能会有更好的角度。
Here is a JSFiddle of the radial tree
数据模型也发生了变化,因为元素现在有了名称,子项和导入(链接)。
var flare =
{
"name": "root",
"children": [
{
"name": "test1.parent1","children": [
{"name": "test1.child11","children": [
{"name": "test1.child111"},
{"name": "test1.child112"}
]}
],"imports": ["test2.parent2","test3.parent3","test4.parent4"]
},
{
"name": "test2.parent2","children": [
{"name": "test2.child21"},
{"name": "test2.child22"},
{"name": "test2.child28","children":[
{"name": "test2.child281"},
{"name": "test2.child282"}
]}
],"imports": ["test3.parent3"]
},
{"name": "test3.parent3","imports": ["test4.parent4"]},
{
"name": "test4.parent4","children": [
{"name": "test4.child41"},
{"name": "test4.child42"}
]
}
]
};
为了慢慢开始,我想将Mike Bostock的non-interactive Hierarchical edge bundling与当前的JSFiddle结合起来,但要记住,之后的交互将成为其中的一部分。
此外,只有第一级必须有链接(父 - 父链接),如下所示(我想要的结果):
我目前最大的问题是HEB没有" root",但树开头只有一个项目。所以到目前为止我所尝试的一切都导致了树的中心一团糟。
请注意,树的中心有一个圆圈,用于覆盖1级链接的根,因此树从1级(父级)开始。
var circle = svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", diameter - 725.3)
.style("fill", "#F3F5F6")
.style("stroke-width", 0.2)
.style("stroke", "black");
理想情况下,父级之间的链接必须在级别(un)折叠时更新,就像它对节点和级别之间的链接一样,但是这可以在以后获得,并且在最初获得第一级之后可能不会那么困难要显示的链接。此外,如有必要,数据模板可能会更改,但所有3条信息都很重要(名称,子项和导入)。
另一种方法是能够将数据更改为不包含根部分,并且它的行为与现在完全相同 部分答案也是受欢迎的。
答案 0 :(得分:0)
我目前最大的问题是HEB没有" root",但树开头只有一个项目。所以到目前为止我所尝试的一切都导致了树的中心一团糟。
鉴于你有一个root,为什么不把它设置为中心"节点"并使其成为径向树,如this? Here是另一个例子,但有多个根。
那就是说,你没有要求一个径向树,即使它听起来会回答你的问题。如果你决心把东西排列成不同镭的圆圈,那么要解决的问题可能就是线条的纵横交错看起来如此混乱"。如果是这种情况,则可以使用不同的排序算法。 Here是一篇文章,它扩展了在D3.js的类似场景中使用不同的排序算法。 D3布局算法也是open source online。
我能找到的最好的资源是this Stack Mathematics Answer。其中有几点特别突出:
答案 1 :(得分:0)
我已经设法在这个JSFiddle中的元素之间添加链接,使用Mike Bostock在原始分层边缘捆绑中找到的部分代码,并将它们添加到可折叠树的径向版本中。但是,在折叠或扩展孩子时,他们不会更新!
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial()
.interpolate("bundle")
.tension(.85)
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
然后在update(source)
:
var middleLinks = packageImports(root);
svg.selectAll("path.middleLink")
.data(bundle(middleLinks))
.enter().append("path")
.attr("class", "middleLink")
.attr("d", line);
“packageImport”功能可以在底部找到。
function packageImports(json) {
var map = {},
imports = [];
console.log(json.children);
// Compute a map from name to node.
json.children.forEach(function(d) {
console.log(d.name)
map[d.name] = d;
});
// For each import, construct a link from the source to target node.
json.children.forEach(function(d) {
if (d.imports) d.imports.forEach(function(i) {
imports.push({source: map[d.name], target: map[i]});
});
});
console.log(imports);
return imports;
}