Ändern Sie die Deckkraft aller Knoten und Kanten rekursiv (d3)

8

UPDATE: Ich habe hier einen JSFiddle erstellt . Bitte posten Sie eine aktualisierte Geige mit Ihrer Antwort.

Ich habe dynamische Filter, die der Benutzer auf Daten anwenden kann, aber sie ändern die Deckkraft der Knoten, um anzuzeigen, was gefiltert und ausgefiltert wird (die gefilterten "out" -Elemente sind noch teilweise sichtbar und die tatsächliche d3 filter() -Funktion) nicht verwendet (absichtlich)). Ich habe auch eine Eigenschaft für jeden Knoten festgelegt, der herausgefiltert wird (z. B. node = {"name": "test", "isFilteredOut": true}; ). Also für die Zwecke dieser Frage, obwohl ich das Wort "Filter" verwende, ist es wirklich nur eine bedingte Stiländerung (und ich werde versuchen, das Wort zu setzen) "filter" in Anführungszeichen in diesem Beitrag als Erinnerung daran).

Das alles funktioniert gut, aber jetzt möchte ich alle untergeordneten Knoten und Kanten von "herausgefilterten" Knoten rekursiv "filtern" und auch die Kante, die den ersten "ausgefilterten" Knoten mit seinem nicht gefilterten Knoten verbindet. aus Elternknoten.

Alle Beispiele, die ich finden kann, beginnen mit einem Klick-Event und haben daher den Luxus, this zu verwenden, um die Daten für den ersten ausgewählten Knoten zu erhalten. Ich habe diesen Luxus nicht , weil der Filter mit einem UI-Element angewendet wird, das nicht im Diagramm selbst enthalten ist.

Ich "filtriere" die Knoten wie folgt:

%Vor%

Was ich im Wesentlichen tun muss, ist:

  1. Wählen Sie rekursiv alle untergeordneten Knoten von aktuell "herausgefilterten" Knoten aus und "filtern" Sie diese auch aus (d. h. ändern Sie ihre Deckkraft auf 0,1 und setzen n.isFilteredOut = true; ).

  2. Ändern Sie die Deckkraft aller Kanten auf 0,1, wobei der Quellknoten oder Zielknoten "herausgefiltert" wird (dh n.isFilteredOut = true; an jedem Ende der Kante)

Was ich versucht habe

Ich weiß nicht, wie ich auf die Daten des Quell- und Zielknotens zugreifen soll, wenn nur der Index von jedem der Kanten angegeben wird (beachte, dass ich keinen this -Knoten habe, mit dem ich von einem Klickereignis anfangen könnte). Ich habe versucht, den von der Kante erhaltenen Knotenindex zu übergeben, um die Knotendaten mit:

zu erhalten %Vor%

Dies führte jedoch dazu, dass Fehler in der d3-Bibliothek im Zusammenhang mit this.node() null waren (also hat die Weitergabe des Index hier nicht funktioniert).

Ich habe auch versucht, Kanten zu behandeln, indem ich die Funktion zum Verarbeiten von Verknüpfungen innerhalb der an die node.style() -Funktion übergebenen Funktion verschachtelte, aber dann versucht, alle Kanten auf alle zu behandeln Knoten und ich kann es nicht bekommen, um das gewünschte Ergebnis zu liefern.

%Vor%

Dies war mein Versuch, Kanten auf beiden Seiten von "herausgefilterten" Knoten herauszufiltern, aber keine der Kanten wurde herausgefiltert, wenn ich dies aus irgendeinem Grund benutzte (es schien, als ob gar nichts passierte). .

UPDATE: Ich habe hier ein JSFiddle erstellt .

Hinweise zur Geige:

  • Ich bin mir bewusst, dass es einfach ist (es soll ein funktionierendes Beispiel sein)
  • Die eigentliche Anwendung enthält Filter, die innerhalb von Typen angewendet werden (selbst wenn nur nach einem bestimmten Gerät / Teil / etc. gesucht wird). Daher ist es wichtig, dass die Logik der Kette nur für diese Knoten mit Bedingungsfolge folgt %Code%
  • In diesem Beispiel führt die richtige Antwort dazu, dass eine Situation entsteht, in der Geräte ausfiltern auch alle Teile herausfiltert
  • Lösungen, die mit node.isFilteredOut = true; selbst filtern, funktionieren nicht, da viele meiner Daten aus verschiedenen JSON-Quellen dynamisch gefüllt werden. Arbeiten Sie gerne mit dataSet , nodes , edges , links und / oder node .
  • Bitte schreiben Sie meine Filtermethode nicht um. Ja, ich weiß link Aussagen sind nicht großartig. Aber das ist keine Frage darüber, wie man am besten unendliche konjunktive Filter anwendet, sondern die Deckkraft von Knoten und Kanten rekursiv auf der Grundlage der angewandten Filter ändert
Dan 22.09.2016, 02:33
quelle

2 Antworten

2

Hier ist ein möglicher Ansatz, der sowohl das rekursive Filtern implementiert (wenn ein Gerät gefiltert wird, dessen Teile gefiltert werden) als auch das Filtern von Links basierend auf dem Filtern ihrer Knoten: Ссылка

Ich habe die Art und Weise, wie Sie den Filter implementieren, geändert. Strings verwenden, um den Filter zu erstellen, und dann wird eval() in diesen Tagen als ziemlich schlecht angesehen, weil Tools mit eval() nicht viel anfangen können, um zum Beispiel Fehler zu erkennen oder den JS-Code im Browser zu optimieren.

Ich filtere direkt auf dataSet , nicht auf den Knoten (wo Sie den type des Knotens abfragen und Strings vergleichen mussten, was langsam ist). Wenn Sie dies direkt auf dem dataSet tun, können Sie auch leicht herausfinden, was das Gerät für ein bestimmtes Teil ist.

Der Trick besteht darin, jedes Mal das gesamte Diagramm neu zu zeichnen und sorgfältig die Auswahlmöglichkeiten exit , enter und update von d3 zu verwenden. Dadurch können Sie auch Animationen hinzufügen, wenn Sie möchten

    
manuBriot 26.09.2016 09:38
quelle
0

Ich weiß, dass Sie sich hier sehr auf die Verwendung von eval konzentrieren, aber Sie könnten Ihre Filterfunktionen einfach umgestalten, um ein Lambda zurückzugeben:

%Vor%

und dann etwas wie folgt machen:

%Vor%

Oder mit reduzieren, wenn Sie Array.every nicht haben:

%Vor%

Oder machen Sie einen rekursiven Iterator, wenn das mehr Ihre Tasche ist. Punkt ist, bedingte Boolesche Auswertung und verzögerte Ausführungen sind nicht etwas, für das Sie eval brauchen, und Sie nehmen einen großen Perf-Treffer, indem Sie eval laufen lassen.

- # Bearbeiten -

Sieht so aus, als ob das DOM hier nicht die Beziehung zwischen Ihrem Gerät und den Teilknoten widerspiegelt. Daher können Sie ein D3-Auswahlobjekt nicht verwenden, um einen bestimmten Teilknoten mit seinem übergeordneten Geräteknoten in Beziehung zu setzen.

Somit ist die rekursive Auswahl der Kinder ein strittiger Punkt.

Alternativ können Sie Ihre Filterfunktionen auch so anpassen, dass sie die Beziehung widerspiegeln - IE, wenn wir nach Teil filtern, geben Sie false für Gerät oder Teil zurück.

Das ist nur eine wirklich nachhaltige Lösung, wenn es nicht so viele Filterbedingungen gibt und Sie bereits die Geschäftslogik kennen, die Sie im Vorfeld verwenden möchten, um sie zu filtern, aber es könnte für Sie funktionieren.

    
Iron Gremlin 29.09.2016 18:51
quelle