d3js:创建可折叠表和嵌套数据的问题



我正在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

最新更新