use*_*289 6 javascript recursion nested d3.js
我有函数式编程的背景,原则上理解递归,但我似乎无法将这些知识转化为D3.js环境.
我在下面有一个hello world脚本,它试图简单地打印嵌套数据结构的内容.遵循其他线程的建议,我可以使用.filter只返回节点,但如何继续此示例递归打印嵌套项?
<!DOCYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="d3.v3.js"></script>
<script>
function draw(data)
{
"use strict";
d3.select("body")
.selectAll("p")
.data(data)
.enter()
.append("p")
.text(function(d) {
if (d instanceof Array) {
return "WHAT DO I PUT HERE?";
}
else {
return d;
};
});
}
</script>
</head>
<body>
Hello world
<script>
draw([1, [2, [1, 2, 3, 4] ], 3, 4, 5]);
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
您需要一个根功能,然后需要一个填充它的递归函数.
function makeNestedListItems (parentLists) {
var item = parentLists.append('li')
.text(function (d) { return d.txt; });
var children = parentLists.selectAll('ul')
.data(function (d) {
return d.children
})
.enter().append('ul');
if (!children.empty()) {
makeNestedListItems(children);
}
}
var data = {
txt: 'root',
children: [{
txt: "a",
children: [{
txt: "aa",
children: [{
txt: "aaa",
children: []
}, {
txt: "aab",
children: []
}
]
}, {
txt: "ab",
children: []
}
]
}, {
txt: "b",
children: [{
txt: "ba",
children: []
}, {
txt: "bb",
children: []
}, {
txt: "bc",
children: []
}
]
}, {
txt: "c",
children: []
}
]
};
var rootList = d3.select('body').selectAll('ul').data([data])
.enter().append('ul');
makeNestedListItems(rootList);
Run Code Online (Sandbox Code Playgroud)
哪个应该产生
做到这一点的简单方法就是避免递归!典型的 D3.js 方法是递归数据并确定布局所需的信息(例如,子级的总大小、嵌套的总深度、每个节点的深度),然后展平结构并使用计算值进行布局。
在此树示例中可以找到一个很好的示例,其中使用内置函数进行计算和展平:
var tree = d3.layout.tree()...
Run Code Online (Sandbox Code Playgroud)
也就是说,如果您真的想尝试直接在布局中进行递归所需的选择体操,您可以这样做。关键是你必须做出选择,然后根据父母的数据设置他们的数据。
在下面的示例中,为了方便起见,我对 maxLevels 进行了硬编码,但您可以在进入循环之前根据数据计算它。
另请注意,我对布局非常懒惰,因为要正确执行此操作,您需要首先对数据进行递归传递,以在开始之前计算每个元素至少有多少个子元素。你可以在这里拉小提琴。
var data = { children: [{
txt: "a", children: [{
txt: "aa", children: [{
txt: "aaa"}, {
txt: "aab"}]}, {
txt: "ab"}]}, {
txt: "b", children: [{
txt: "ba"}, {
txt: "bb"}, {
txt: "bc"}]}, {
txt: "c"}]};
var svg = d3.selectAll("svg");
svg.attr({ width: 500, height: 500});
var recurse = svg.selectAll("g.level0").data([data]).enter()
.append("g").classed("level0", true);
var maxLevels = 4;
for (var level = 0; level < maxLevels; level++) {
var nextLevel = level + 1;
var next = svg.selectAll("g.level" + level).filter(function (d) {
return d.children !== undefined;
});
next.selectAll("g.level" + nextLevel)
.data(function (d) { return d.children; })
.enter().append("g")
.attr("class", function (d) {
return "level" + nextLevel + " " + d.txt;
})
.attr("transform", function (d, i) {
return "translate(" + (nextLevel * 25) + "," + (i * 10 * (5 - level) + 15) + ")";
});
next.selectAll("text.level" + nextLevel)
.data(function (d) { return d.children; })
.enter().append("text")
.classed("level" + level, true)
.attr("x", function (d, i, j) { return nextLevel * 25; })
.attr("y", function (d, i, j) {
return j * (10 * (10 - level)) + (i+1) * 15;
})
.attr("fill", "black")
.text(function (d) { return d.txt; });
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4456 次 |
| 最近记录: |