Javascript D3 v4将树节点拖放到新的父节点和子节点中

Javascript D3 v4将树节点拖放到新的父节点和子节点中,javascript,d3.js,Javascript,D3.js,在使用D3中的4个节点时,我在调整下面的代码片段以完全更新节点及其所有子节点时遇到了一些麻烦 此代码在dragend事件中将一个节点拖放到另一个父节点时激发。其目的是将拖动的节点从其当前父节点中移除,并将其插入到新的父节点和子节点中 当前的代码实际上仍在执行使用v4时的预期操作,但在新版本中,似乎还有一些事情需要更新到draggingNode,以便它能够正确地过渡到新位置。至少,draggingNode需要应用到它的新父节点,并将其深度更新到它在树中的新位置。draggingNode的每个子节点

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

此代码在dragend事件中将一个节点拖放到另一个父节点时激发。其目的是将拖动的节点从其当前父节点中移除,并将其插入到新的父节点和子节点中

当前的代码实际上仍在执行使用v4时的预期操作,但在新版本中,似乎还有一些事情需要更新到draggingNode,以便它能够正确地过渡到新位置。至少,draggingNode需要应用到它的新父节点,并将其深度更新到它在树中的新位置。draggingNode的每个子节点还需要将其深度更新到树中的新位置

selectedNode:节点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,遇到了同样的问题。看起来D3V4比以前做了更多的内部簿记,搞乱节点属性不是个好主意。 当使用打字时,一些属性实际上被标记为只读,就像深度一样,它已经告诉你一些事情

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

谢谢,我接受了你的建议&到目前为止,这对各种树mod都很有效。
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);
}