簡體   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