2017-03-04 119 views
0

在使用4个D3时,我在调整下面的代码片段以完全更新节点及其所有子节点时遇到了一些问题。D3 v4将树节点拖放到新的父母孩子中

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

当前的代码实际上仍然做它使用v4的目的,但现在新版本似乎有更多的东西需要更新到“draggingNode”,所以它会正常转换到新的位置。至少,“draggingNode”需要应用它的新“父”,并将其更新为“深度”,以将其新位置放在树内。 “draggingNode”的每个孩子也需要将其“深度”更新为树中的新位置。

  • selectedNode:节点 “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; 

这个伟大的工程!问题是它只能在没有孩子的节点上工作。子节点属性需要更新。

问题IS

我如何更新“draggingNode”,及其所有的孩子,让他们的性质适当进行调整,他们的新父母和深度?

是否有我可以使用像hierarchystratify正确更新它们的功能?如果是这样,我不太清楚如何使这些工作。或者,也许在API中没有可用的功能,我只需要遍历所有的孩子并更新他们的深度?

回答

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); 
    } 
} 

这里是我结束了..

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); 
} 
0

我升级我的D3树V4并有同类问题。看起来像D3 V4比以前做更多的内部簿记,搞乱节点属性并不是一个好主意。 使用类型时,一些属性实际上标记为只读(如深度),它已经告诉你一些事情...

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

+0

谢谢,我采纳了你的建议,到目前为止,这适用于各种树模。 – timmacp