2017-03-04 6 views
0

Ich habe ein wenig Mühe, den Ausschnitt unten zu optimieren, um einen Knoten und alle seine Kinder vollständig zu aktualisieren, wenn Sie 4 von D3 verwenden.D3 v4 Drag/drop Baum Knoten in neue Eltern Kinder

Dieser Code wird ausgelöst, wenn ein Knoten in einen anderen übergeordneten Knoten gezogen und abgelegt wird (beim Ereignis "dragend"). Der Zweck besteht darin, den gezogenen Knoten von seinem aktuellen Elternknoten zu entfernen und ihn in ein neues Elternkind einzufügen.

Der aktuelle Code tut tatsächlich immer noch das, was er bei der Verwendung von v4 tun soll, aber jetzt scheint es bei der neuen Version noch ein paar Dinge zu geben, die auf den "DraggingNode" aktualisiert werden müssen Position. Zumindest muss der "draggingNode" angewendet werden, es ist neu "übergeordnet" und aktualisiert seine "Tiefe" auch dort, wo sich seine neue Position innerhalb der Struktur befindet. Jedes Kind des "DraggingNode" muss auch seine "Tiefe" an seine neue Position innerhalb der Baumstruktur anpassen.

  • selectedNode: Knoten, der die "draggingNode" auf (neue parent) fallen gelassen
  • draggingNode: Knoten momentan gezogen wird

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

Ich glaube der Code oben kann unberührt bleiben, aber was Ich muss noch einige Updates für den "DraggingNode" hinzufügen, damit er korrekt aktualisiert werden kann.

Meine ersten Gedanken waren einfach folgendes Snippet hinzuzufügen oben, kurz bevor es in die „selectedNode“ Array hinzufügen:

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

Dies funktioniert gut! Das Problem ist, dass es nur auf Knoten ohne Kinder funktioniert. Untergeordnete Knoteneigenschaften müssen aktualisiert werden.

FRAGE

Wie kann ich die „draggingNode“ aktualisieren, und alle seine Kinder, so dass ihre Eigenschaften zu ihren neuen Eltern und Tiefen richtig eingestellt sind?

Gibt es eine Funktion, die ich wie hierarchy oder stratify verwenden kann, um sie ordnungsgemäß zu aktualisieren? Wenn dem so ist, bin ich mir nicht ganz sicher, wie ich diese Arbeit machen soll. Oder vielleicht gibt es keine Funktionen innerhalb der API und ich muss nur alle Kinder durchlaufen und ihre Tiefen aktualisieren?

Antwort

1

Nun stellt sich heraus, dass ich eine Lösung gefunden habe, die für mich gut zu funktionieren scheint. Ich habe am Ende eine Funktion erstellt, die alle Nachkommen des gezogenen Knotens durchquert und deren Knotentiefe aktualisiert.

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

Hier ist, was ich am Ende mit ..

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

ich nur V4 meinem D3 Baum aufgerüstet und hatte die gleiche Art von Problemen. Sieht so aus, als würde D3 V4 mehr interne Buchhaltung als vorher machen und es ist keine gute Idee, sich mit den Knoteneigenschaften herumzuschlagen. Bei der Verwendung von Typings werden einige Eigenschaften tatsächlich als schreibgeschützt markiert (wie die Tiefe), was Ihnen bereits etwas sagt ...

Stattdessen reflektieren Sie das neue Layout, indem Sie Ihre eigene Datenstruktur aktualisieren und den Stammknoten mit d3.hierarchy() aktualisieren. Rufen Sie dann Ihre Update-Methode mit dem neuen Root auf. Das funktionierte perfekt für mich, kein Hacking erforderlich!

+0

Danke, ich nahm Ihren Vorschlag und soweit funktioniert das gut für alle Arten von Baummods. – timmacp