2017-03-04 9 views
0

D3のうち4つを使用しているときにノードとそのすべての子を完全に更新するには、以下のスニペットを調整するのに少し問題があります。D3 v4ツリーノードを新しい親にドラッグする

このコードは、ノードがドラッグされて別の親ノードにドロップされると(「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); 
    } 
    
    :ノードが現在

ターゲットスニペットを(full source code)ドラッグされています

私は上記のコードは変わらないと思っていますが、私はそれが正しく更新することができるように "draggingNode"のいくつかの更新を追加する必要があります。

私の最初の考えは単純に「selectedNodeの」アレイにそれを追加する前に、上記のスニペットに以下を追加しました:

draggingNode.parent = selectedNode; 
draggingNode.depth = selectedNode.depth + 1; 

これは素晴らしい作品!問題は、子なしのノードでのみ機能することです。子ノードのプロパティを更新する必要があります。

QUESTIONは、そのプロパティが適切に彼らの新しい両親や深さに調整されるように、どのように私は、「draggingNode」を更新し、そのすべての子ができ

IS?

hierarchyまたはstratifyのように使用して正しく更新できる機能はありますか?もしそうなら、私はそれらの仕事をどうやって作るのかについてはあまりよく分かりません。 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); 
    } 
} 

は、ここで私は、私はちょうどV4への私のD3ツリーをアップグレードした。..

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.hierarchy()を使用してルートノードを更新します。次に、新しいルートで更新メソッドを呼び出します。 これは私のために完全に機能し、ハッキングは必要ありません!

+0

ありがとうございます、私はあなたの提案を受け取りました。これまでのところ、これはあらゆる種類のツリーモッズでうまくいきます。 – timmacp

関連する問題