繁体   English   中英

D3 v4拖放树节点到新的父级子级中

[英]D3 v4 drag/drop tree node into new parents children

使用D3中的4个时,我在调整下面的代码片段以完全更新节点及其所有子节点时遇到了一些麻烦。

当将一个节点拖放到另一个父节点中时(在“ dragend”事件上),将触发此代码。 目的是将拖动的节点从其当前父节点中删除,然后将其插入新的父子节点中。

当前的代码实际上仍然按照使用v4时的意图进行操作,但是现在使用新版本时,似乎还需要更新一些内容到“ draggingNode”,以便可以正确过渡到新位置。 至少需要将“ draggingNode”应用为新的“父”,并将其“深度”更新为树中新位置。 “ draggingNode”的每个子节点还需要将其“深度”更新为树中的新位置。

  • selectedNode :放置了“ draggingNode”的节点(新父节点)
  • draggingNode :当前被拖动的节点

目标代码段( 完整的源代码 ):

var index = draggingNode.parent.children.indexOf(draggingNode);
if (index > -1) {
    draggingNode.parent.children.splice(index, 1);
    // had to update the "draggingNode" parent "children" array if it's 
    // empty otherwise the "firstWalk()" core function throws an error when
    // trying to call "children[0]".
    if (draggingNode.parent.children.length == 0) {
        draggingNode.parent.children = null;
    }
}
if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') {
    if (typeof selectedNode.children !== 'undefined') {
        selectedNode.children.push(draggingNode);
    } else {
        selectedNode._children.push(draggingNode);
    }
} else {
    selectedNode.children = [];
    selectedNode.children.push(draggingNode);
}

我相信上面的代码可以保持不变,但是我需要做的是为“ draggingNode”添加一些更新,以便可以正确地对其进行更新。

我最初的想法是在将其添加到“ selectedNode”数组之前,将以下内容简单地添加到上面的片段中:

draggingNode.parent = selectedNode;
draggingNode.depth = selectedNode.depth + 1;

这很棒! 问题在于它仅适用于没有子节点的节点。 子节点属性需要更新。

问题是

如何更新“ draggingNode”及其所有子级,以便将其属性适当地调整为新的父级和深度?

有没有我可以使用的功能(例如层次结构分层 结构)来正确更新它们? 如果是这样,我不太确定如何使这些工作。 也许API内没有可用的功能,我只需要遍历所有子项并更新其深度?

好吧,事实证明我想出了一个对我来说似乎很好用的解决方案。我最终创建了一个遍历拖动节点的所有后代并更新其节点深度的函数。

function setNodeDepth(d) {
    d.depth = d == root ? 0 : d.parent.depth + 1;
    if (d.children) {
        d.children.forEach(setNodeDepth);
    } else if (d._children) {
        d._children.forEach(setNodeDepth);
    }
}

这就是我最终得到的..

var index = draggingNode.parent.children.indexOf(draggingNode);
if (index > -1) {
    draggingNode.parent.children.splice(index, 1);
    // had to update the "draggingNode" parent "children" array if it's 
    // empty otherwise the "firstWalk()" core function throws an error when
    // trying to call "children[0]".
    if (draggingNode.parent.children.length == 0) {
        draggingNode.parent.children = null;
    }
}

// update the "draggingNode" parent as well as update all its children 
// so that their properties are properly adjusted to their new depths.
draggingNode.parent = selectedNode;
draggingNode.descendants().forEach(setNodeDepth);

// check for visible children.
if (selectedNode.children) {
    selectedNode.children.push(draggingNode);
// check for hidden children.
} else if (selectedNode._children) {
    selectedNode._children.push(draggingNode);
// no children exist, create new children array and add "draggingNode".
} else {
    selectedNode.children = [];
    selectedNode.children.push(draggingNode);
}

我刚刚将D3树升级到V4,并且遇到了同样的问题。 看起来D3 V4比以前做更多的内部记账,并且弄乱节点属性不是一个好主意。 使用类型时,实际上会将某些属性标记为只读(例如,深度),这已经告诉了您一些信息...

而是通过更新自己的数据结构来反映新的布局,并使用d3.hierarchy()刷新根节点。 然后使用新的根调用您的更新方法。 这对我来说非常有效,不需要黑客!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM