我正在d3js中创建一个可折叠的表,并且我所使用的数据结构的嵌套性质一直存在问题。数据的组织方式如下:
var source = [
{name: William, age: 40, children: [{name: Billy, age: 10},{name:Charles, age: 12}]},
{name: Nancy, age: 35, children: [{name: Sally, age:8}]}
]
当我第一次创建表时,我将children
数组移动到每个相应父对象中的_children
对象中,如下所示:
tableData.forEach(function(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
});
使用d3js的典型数据输入,我可以填充表中每个父项的行和坐标。
source.forEach(function(d) {
d.x = x0;
d.y = y0;
var parentX = x0,
parentY = y0;
y0 += barHeight + padding;
if (d.children) {
d.children.forEach(function(data) {
data.x = x0;
data.y = y0;
data.parentX = parentX;
data.parentY = parentY;
y0 += barHeight + padding;
shownChildren.push(data);
})
}
});
我使用常用的数据选择方法:
var tableRow = tableSvg.selectAll('.tableRow')
.data(source);
var rowEnter = tableRow.enter()
.append("g")
.classed("tableRow", true)
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
});
以及放置代表每行的矩形:
var rowRect = rowEnter.append("rect")
.attr("height", barHeight)
.attr("width", barWidth)
.style("fill", color)
.on("click", click);
var rowText = rowEnter.append("text")
.attr("dy", 15)
.attr("dx", 5.5)
.text(function(d) {
if (d.name.length > 70) {
return d.name.substring(0, 67) + "...";
} else {
return d.name;
}
})
.on("click", click);
单击一行后,行移动以为添加的子行腾出空间,和_children
数组移回children
,上面的代码为每个子行分配一个位置,然后显示它们:
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
updateTable(source);
}
然而,当我使用与上面的父母完全相同的方式为每个孩子创建行时,就会出现一个问题。我当前的实现构建了一个数组shownChildren
(如第三个代码块所示),并用子级填充表中的间隙。最初,实现似乎运行良好,但当您单击行时,每个子行的位置都会发生变化。
我对目前造成问题的原因没有任何猜测。
以下是我在jsfiddle上的代码概要。
我遇到的问题是,每次都要用不同数量的子对象重建shownChildren
数组。我通过将所有的children
和_children
添加到shownChildren
数组中(始终按相同的顺序!)并将每个_children
隐藏在各自的父数组后面来解决这个问题。
更新的jsfiddle