我在调整下面的代码片段时遇到一些麻烦,以便在使用4个D3时完全更新节点及其所有子节点。
当节点被拖放到另一个父节点时(#34; dragend" event),此代码将触发。它的目的是从当前父节点中删除拖动的节点,并将其插入新的父节点子节点。
当前代码实际上仍然执行它在使用v4时要执行的操作,但现在使用新版本时,似乎还有一些事情需要更新到" draggingNode"所以它将适当地过渡到新的位置。至少," draggingNode"需要应用它新的"父母"并更新它的深度"它在树中的新位置。 " draggingNode"的每个孩子。也需要有其深度"更新到它在树中的新位置。
目标片段(full source code):
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"及其所有子项,以便将其属性正确调整为新的父项和深度?
我是否可以使用hierarchy或stratify这样的功能来正确更新它们?如果是这样,我不太确定如何使这些工作。或者API中没有可用的功能,我只需循环遍历所有孩子并更新他们的深度?
答案 0 :(得分:1)
好吧结果我提出了一个似乎对我有用的解决方案..我最终创建了一个函数来遍历拖动节点的所有后代并更新它们的节点深度。
!
这是我最终的结果..
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);
}
}
答案 1 :(得分:0)
我刚刚将D3树升级到V4并遇到了同样的问题。看起来D3 V4比以前做更多的内部簿记,并且弄乱节点属性并不是一个好主意。 当使用打字时,一些属性实际上被标记为只读(如深度),它已经告诉你一些东西......
相反,通过更新自己的数据结构并使用d3.hierarchy()刷新根节点来反映新布局。然后使用新的root调用update方法。 这对我来说非常合适,不需要黑客攻击!