在d3.js中如何折叠/展开树的子节点?

9
我正在构建一棵树形结构(或者说是修改一个示例,使用我的自定义数据和json),并且我想要创建一些功能:
我的树的布局与示例中的树相同: http://mbostock.github.com/d3/ex/cluster.html 我正在添加(到圆圈上)一个onclick事件,我希望它可以折叠所点击节点的子节点。也就是说,当用户单击与节点相关联的steelblue圆圈时,我希望该节点的子节点消失。
我已经仔细查阅了文档,但没有找到任何允许我使节点折叠或消失的内容。
我该怎么办?
4个回答

22

同意。谢谢,这是一个很棒的工具。如果可以的话,我会给它+2。 - Pythonic
@mbostock非常感谢您提供的精美可视化。您在https://bl.ocks.org/mbostock/4339083上的作品版本可能更容易让其他用户进行适应。 - XValidated

2
有几种方法可以做到这一点,其中一种是使用常规样式来隐藏子元素的标记(opacity:0或display:none)。但是,这只是使数据不可见,树保持其形状,就好像数据存在一样,只是看不见它。
通常,您会希望树假装没有数据,并相应地更新,为此,您可以使用与上面链接中力导向布局示例相同的方法。
它可以概括为: 1) 使用函数构建d3树 2) 将点击事件附加到可折叠节点 3) 点击事件重命名节点的children属性,并调用第1)步中的函数,该函数重新绘制不包含该节点子级的树。
以下是nkoren答案中链接的相关代码(http://bl.ocks.org/1062288)。
function update() { 
    // build the tree layout here
    //  append on("click", click) to the collapsible nodes
}

// Toggle children on click
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update();
}

1

很遗憾,我还在学习D3,不确定如何最好地回答你的问题。但是这里有一个力导向布局,允许你通过单击节点来显示/隐藏它们,这可能会给你一些想法:http://bl.ocks.org/1062288


强制定向布局对于图形可视化很好,但对于树结构并不理想。 - mariosangiorgio
如果您查看源代码,可以看到它不是强制定向布局也无关紧要,相同的解决方案可用于任何DAG(即图中没有循环),包括树。我会在特定答案中添加具体代码(以防链接失效)。 - forforf

0
创建一个折叠函数,仅在节点具有子节点时才在单击时执行。我分享了下面的代码,这对我很有效:
  collapse = (d) => {
    if (d.children) {
      d._children = d.children;
      d._children.forEach((d) => this.collapse(d));
      d.children = null;
    }
  }

  click = (d) => {
    console.log('click: ', d);
    if (d.children) {
      this.collapse(d);
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    this.updateChart(d);
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接