【问题标题】:D3.js collapsible tree - expand/collapse intermediate nodesD3.js 可折叠树 - 展开/折叠中间节点
【发布时间】:2013-07-01 04:42:47
【问题描述】:

我有一个 D3.js collapsible tree,它有一堆节点。树中有几条路径,其中存在只有一个子节点的节点序列。想象一下这棵树:

               5
              /
1 - 2 - 3 - 4 -6
              \
               7

1节点被点击时,我希望它变成:

      5
     /
1 - 4 -6
     \
      7

现在我的代码正常展开和折叠节点。如何选择那些 intermediate 节点,以便像现在一样使用切换功能定位它们?

我的代码与示例中的基本相同,除了我添加的一些与此问题无关的内容。 toggle() 函数接收一个指向node 的指针,并使可见的子节点(在children 数组中)不可见(通过将它们移动到_children 数组中)。这会将 所有 孩子(以及孙子、曾孙...)打到该特定节点,但我需要它在找到具有 exactly 1 的节点时继续孩子,那么,如果它找到一个没有孩子的节点,我希望它是可见的;如果节点有超过 1 个子节点,我希望它从那时起显示所有子节点。

这是在其中一个节点中调用 onclick 的 toggle() 函数代码:

function toggle(d) {
    var myLength;
    if(d.children){myLength = d.children.length;}
    else{myLength=0;}

    if (myLength === 1) {
        //next will be the first node we find with more than one child
        var next = d.children[0];
        for (;;) {if(next.hasOwnProperty('children')){
            if (next.children.length === 1) {
                next = next.children[0];
            } else if (next.children.length > 1) {
                break;
                }
            } else {
                // you'll have to handle nodes with no children
                break;
            }
        }
        d._children = d.children;
        d.children = [next];
    }else{
        if (d.children) {
            d._children = d.children;
            d.children = null;
        } else {
            d.children = d._children;
            d._children = null;
        }
    }
}

【问题讨论】:

    标签: javascript arrays d3.js


    【解决方案1】:
    function toggleChildren(d) {
    
        var myLength;
    
        if (d.toggle !== "close") {
            if(d.children){
                myLength = d.children.length;
            }else{
                myLength=0;
            }
            d._children = d.children;
            if (myLength === 1){
                //next will be the first node we find with more than one child
                var next = d.children[0];
                for (;;) {if(next.hasOwnProperty('children')){
                    if (next.children.length === 1) {
                        next = next.children[0];
                    } else if (next.children.length > 1) {
                        break;
                    }
                } else {
                    // you'll have to handle nodes with no children
                    break;
                }
                }
                d.children = [next];
                //d._children = d.children;
                d.toggle = "close"
            }else{
                if (d.children) {
                    d._children = d.children;
                    d.children = null;
                } else {
                    d.children = d._children;
                    d._children = null;
                }
            }
        }else{
            if(d.toggle == "close"){
                var _children = d.children;
                d.children  = d._children;
                d._children =   _children;
                d.toggle = "open"
            }else{
                if (d.children) {
                    d._children = d.children;
                    d.children = null;
                } else {
                    d.children = d._children;
                    d._children = null;
                }
            }
    
        }
        return d;
    }
    

    【讨论】:

    • 您能否提供更多关于您的解决方案的见解?
    【解决方案2】:

    那个切换功能不做任何类型的逻辑检查,它只是删除和添加孩子。为了做你想做的事,你需要使用一些逻辑和数据遍历,但这并非不可能。试试这样的:

    function toggle(d) {
        if (d.children.length === 1) {
            //next will be the first node we find with more than one child
            var next = d.children[0];
            for (;;) {
                if (next.children.length === 1) {
                    next = next.children[0];
                } else if (next.children.length > 1) {
                    break;
                } else {
                    //you'll have to handle nodes with no children
                }
            }
    
            d._children = d.children;
            d.children = [next];
        }
    }
    

    【讨论】:

    • 感谢您的回复!无子节点实际上不需要任何特定行为——即,它们不是toggable。这大部分都有效,除了反向操作 - 当我单击折叠的序列时 - 它不会再次展开。此外,如果序列以无子节点结尾,我也无法折叠它。有什么想法吗?
    • 哦!并且拥有超过 1 个子节点的节点也不能再折叠了……:S
    • 我已经围绕您的示例进行了调整,现在,拥有超过 1 个子节点的节点表现得像他们应该做的那样。单子节点序列中的节点折叠,但不展开。如果序列以无子节点结束,则它不会折叠/展开。检查我上面更新的代码。
    • 弄清楚了以next.hasOwnProperty 位结尾的无子节点的序列。现在只需要让它恢复。愿意帮忙吗?
    • 我发誓这些评论通知从未出现在我的收件箱中。对于那个很抱歉。如果您仍然遇到问题,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多