隐藏D3.js中不相关的父节点,但保留子节点

3
我正在尝试使用D3.js完成此操作,但无法找到实现方式。
我的目标是:当一个人点击根节点(第0级)时,显示子元素(第1级)。当一个人点击其中一个子节点(第1级)时,它应该显示其子节点(第2级)以及父级和父级的父级(第1级,这是用户点击的内容),但隐藏所有不相关的父级(来自第1级)。
让我用图片解释一下。

在jQuery中,您可以通过调用 $('selector').siblings()。hide() 来隐藏节点的兄弟节点。 - jwatts1980
你是想使用d3.layout.tree()完成这个任务,还是针对DOM元素的更一般情况提出了问题? - davidhwang
是的!我正在尝试使用d3.layout.tree()来完成它。 - user3418870
1
你目前尝试了什么?你的设置是什么?具体哪里出了问题?为了获得更进一步的帮助,你需要提供一些代码。请考虑组合一个JSFiddle来进行测试。 - altocumulus
1
你看过这个示例展示的可折叠树形布局吗?如果不完全符合你的需求,它也很好地介绍了基础知识。 - altocumulus
1个回答

6
你可以使用类似于http://bl.ocks.org/benlyall/4fea200ebebb273aa4df的方法进行操作。
我从http://bl.ocks.org/mbostock/4339083进行了分支并进行了一些更改:
  1. Added a new property to each node .all_children which keeps track of all children. We need this, or something similar since .children contains the child nodes currently displayed, and ._children is used by the existing code to determine if a node contains children or not (and sets the style accordingly).

    Also added a .hidden property that helps to determine whether or not the node should be displayed.

    These are added after loading the data:

    d3.json("flare.json", function(error, flare) {
        root = flare;
        root.x0 = height / 2;
        root.y0 = 0;
    
        function collapse(d) {
            if (d.children) {
                d.all_children = d.children;
                d._children = d.children;
                d._children.forEach(collapse);
                d.children = null;
                d.hidden = true;
            }
        }
    
        root.all_children = root.children;
        root.children.forEach(collapse);
        root.children.forEach(function(d) { d.hidden = false; });
        root.hidden = false;
        update(root);
    });
    
  2. Updated the update function to reflect the new changes and only draw the nodes that are supposed to be drawn:

    function update(source) {
    
        // Compute the new tree layout.
        var nodes = tree.nodes(root).filter(function(d) { return !d.hidden; }).reverse(),
        links = tree.links(nodes);
    

    The nodes variable is set to only contain nodes that are NOT hidden.

  3. Updated the click handler to correctly set the state of the nodes in the display:

    // Toggle children on click.
    function click(d) {
        if (d.children) {
            d._children = d.children;
            d.children = null;
            if (d._children) {
                d._children.forEach(function(n) { n.hidden = true; });
    
                if (d.parent) {
                    d.parent.children = d.parent.all_children;
                    d.parent.children.forEach(function(n) {
                        n.hidden = false;
                    });
                }
            }
        } else {
            d.children = d._children;
            d._children = null;
            if (d.children) {
                d.children.forEach(function(n) { n.hidden = false; });
    
                if (d.parent) {
                    d.parent.children = [d,];
                    d.parent.children.filter(function(n) { return n !== d; }).forEach(function(n) {
                        n.hidden = true;
                    });
                }
            }
        }
        update(d);
    }
    

    The first part of the if statement is called when we're collapsing a node, in which case, we need to display all of the siblings of the clicked node by setting d.parent.children to d.parent.all_children and setting each of those nodes to .hidden = false. And we need to hide all the children of the clicked node by setting d.children = null and then setting each node in d._children to hidden.

    The second part of the if statement is called when we're expanding a node, in which case, we need to hide its siblings (set .hidden to true) and update the .children property of the clicked node's .parent node so that only the clicked node is listed as a child.


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