2017-03-04 139 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