Entwicklung dynamischer Baumdiagramme mit SVG und Vue.js.

Das Material, dessen Übersetzung wir heute veröffentlichen, ist dem Prozess der Entwicklung eines Visualisierungssystems für dynamische Baumdiagramme gewidmet. Zum Zeichnen kubischer Bezier-Kurven wird hier die SVG-Technologie (Scalable Vector Graphics, Scalable Vector Graphics) verwendet. Die reaktive Arbeit mit Daten wird von Vue.js organisiert.

Hier ist eine Demoversion des Systems, mit der Sie experimentieren können.


Interaktives Baumdiagramm

Durch die Kombination der leistungsstarken Funktionen von SVG und dem Vue.js-Framework konnten wir ein System zum Erstellen von Diagrammen erstellen, die datenbasiert, interaktiv und anpassbar sind.

Ein Diagramm ist eine Sammlung kubischer Bezier-Kurven, die an einem Punkt beginnen. Die Kurven enden an verschiedenen Punkten in gleichem Abstand voneinander. Ihre endgültige Position hängt von den vom Benutzer eingegebenen Daten ab. Dadurch kann das Diagramm reaktiv auf Datenänderungen reagieren.

Zuerst werden wir darüber sprechen, wie Bezier-Kubikkurven gebildet werden, dann werden wir herausfinden, wie sie im Koordinatensystem des <svg> -Elements dargestellt werden, und über das Erstellen von Masken für Bilder sprechen.

Die Autorin des Materials sagt, dass sie viele Illustrationen für ihn vorbereitet hat, um ihn verständlich und interessant zu machen. Der Zweck des Materials ist es, jedem zu helfen, das Wissen und die Fähigkeiten zu erwerben, die für die Entwicklung seiner eigenen Diagrammsysteme erforderlich sind.

Svg


▍ Wie entstehen kubische Bezier-Kurven?


Die in diesem Projekt verwendeten Kurven werden als Cubic Bezier Curve bezeichnet. Die folgende Abbildung zeigt die Schlüsselelemente dieser Kurven.


Schlüsselelemente einer Bezier-Kubikkurve

Die Kurve wird durch vier Koordinatenpaare beschrieben. Das erste Paar (x0, y0) ist der (x0, y0) der Kurve. Das letzte Koordinatenpaar (x3, y3) ist der letzte Bezugspunkt.

Zwischen diesen Punkten sehen Sie die sogenannten Kontrollpunkte. Dies ist der Punkt (x1, y1) und der Punkt (x2, y2) .

Die Position der Kontrollpunkte in Bezug auf die Kontrollpunkte bestimmt die Form der Kurve. Wenn die Kurve nur durch den Start- und Endpunkt, die Koordinaten (x0, y0) und (x3, y3) , würde diese Kurve wie ein diagonal angeordnetes gerades Segment aussehen.

Jetzt werden wir die Koordinaten der vier oben beschriebenen Punkte verwenden, um die Kurve mit dem SVG <path> -Element zu zeichnen. Hier ist die Syntax, die im <path> -Element zum Erstellen kubischer Bezier-Kurven verwendet wird:

 <path D="M x0,y0 C x1,y1 x2,y2 x3,y3" /> 

Der Buchstabe , der im Code zu sehen ist, ist eine Abkürzung für Cubic Bezier Curve. Kleinbuchstabe ( c ) bedeutet die Verwendung relativer Werte, Großbuchstabe ( C ) bedeutet die Verwendung absoluter Werte. Ich verwende absolute Werte, um das Diagramm zu erstellen. Dies wird durch den im Beispiel verwendeten Großbuchstaben angezeigt.

▍Erstellen eines symmetrischen Diagramms


Symmetrie ist ein zentraler Aspekt dieses Projekts. Um ein symmetrisches Diagramm zu erstellen, habe ich nur eine Variable verwendet, die auf ihrer Grundlage Werte wie Höhe, Breite oder Koordinaten der Mitte eines bestimmten Objekts empfängt.

Nennen wir diese variable size . Da das Diagramm horizontal ausgerichtet ist, kann die Größenvariable als der gesamte horizontale Raum betrachtet werden, der dem Diagramm zur Verfügung steht.

Weisen Sie dieser Variablen einen realistischen Wert zu. Wir werden diesen Wert verwenden, um die Koordinaten der Diagrammelemente zu berechnen.

 size = 1000 

Ermitteln der Koordinaten von Diagrammelementen


Bevor wir die Koordinaten finden können, die zum Erstellen des Diagramms erforderlich sind, müssen wir uns mit dem SVG-Koordinatensystem befassen.

▍Koordinatensystem und Ansichtsfeld


Das Attribut des <svg> viewBox in unserem Projekt sehr wichtig. Tatsache ist, dass es das Benutzerkoordinatensystem des SVG-Bildes beschreibt. Einfach ausgedrückt, bestimmt die viewBox die Position und Größe des viewBox , in dem das auf dem Bildschirm sichtbare SVG-Bild erstellt wird.

Das viewBox Attribut besteht aus vier Zahlen, die die Parameter des Koordinatensystems und die folgenden in dieser Reihenfolge angeben: min-x , min-y , width , height . Die Parameter min-x und min-y legen den Ursprung des Benutzerkoordinatensystems fest, die Parameter width und height legen die Breite und Höhe des angezeigten Bildes fest. So könnte das viewBox Attribut aussehen:

 <svg viewBox="min-x min-y width height">...</svg> 

Die oben beschriebene Größenvariable wird verwendet, um die width und Höhenparameter dieses Koordinatensystems zu steuern.

Später im Abschnitt auf viewBox binden wir die viewBox an eine berechnete Eigenschaft, um die Werte für width und height anzugeben. Darüber hinaus werden in unserem Projekt die Eigenschaften min-x und min-y immer auf 0 gesetzt.

Beachten Sie, dass wir die Attribute height und width des <svg> -Elements selbst nicht verwenden. Wir werden sie mit CSS auf width: 100% und height: 100% einstellen. Auf diese Weise können wir ein SVG-Bild erstellen, das sich flexibel an die Seitengröße anpasst.

Nachdem das Benutzerkoordinatensystem nun zum Zeichnen eines Diagramms bereit ist, wird die Größenvariable zur Berechnung der Koordinaten der Diagrammelemente verwendet.

▍ Unveränderliche und dynamische Koordinaten



Diagrammkonzept

Der Kreis, in dem die Zeichnung angezeigt wird, ist Teil des Diagramms. Deshalb ist es wichtig, es von Anfang an in die Berechnungen einzubeziehen. Lassen Sie uns anhand der obigen Abbildung die Koordinaten für den Kreis und für eine experimentelle Kurve herausfinden.

Die Höhe des Diagramms ist in zwei Teile unterteilt. Dies sind topHeight (20% der size ) und bottomHeight (die restlichen 80% der size ). Die Gesamtbreite des Diagramms ist in zwei Teile unterteilt - die Länge jedes einzelnen beträgt 50% der size .

Dies macht die Schlussfolgerung der halfSize nicht besonders erklärungsbedürftig (hier werden die Indikatoren halfSize und topHeight verwendet). Der Parameter radius wird auf die Hälfte des Werts von topHeight . Dank dessen passt der Kreis perfekt in den verfügbaren Raum.

Schauen wir uns nun die Koordinaten der Kurven an.

  • Die Koordinaten (x0, y0) definieren den (x0, y0) der Kurve. Diese Koordinaten bleiben ständig konstant. Die x0 Koordinate ist der Mittelpunkt des Diagramms (halbe size ), und y0 ist die Koordinate, an der der untere Rand des Kreises endet. Daher wird in der Formel zur Berechnung dieser Koordinate der Radius des Kreises verwendet. Infolgedessen können die Koordinaten dieses Punktes durch die folgende Formel ermittelt werden : (50% size, 20% size + radius) .
  • Die Koordinaten (x1, y1) sind der erste Kontrollpunkt der Kurve. Es bleibt auch für alle Kurven unverändert. Wenn wir nicht vergessen, dass die Kurven symmetrisch sein sollten, stellt sich heraus, dass die Werte von x1 und y1 immer halb so size wie die size . Daher die Formel für ihre Berechnung: (50% size, 50% size) .
  • Die Koordinaten (x2, y2) repräsentieren den zweiten Kontrollpunkt der Bezier-Kurve. Hier gibt x2 an, welche Form die Kurve haben soll. Dieser Indikator wird für jede Kurve dynamisch berechnet. Und der Indikator y2 wird nach wie vor halb so size . Daher die folgende Formel zur Berechnung dieser Koordinaten: (x2, 50% size) .
  • Die Koordinaten (x3, y3) sind der (x3, y3) der Kurve. Diese Koordinate gibt an, wo Sie das Zeichnen der Linie beenden möchten. Hier wird der Wert von x3 wie x2 dynamisch berechnet. Und y3 nimmt einen Wert an, der 80% der size . Als Ergebnis erhalten wir die folgende Formel: (x3, 80% size) .

Wir schreiben den Code für das <path> -Element allgemein neu und berücksichtigen dabei die soeben abgeleiteten Formeln. Die oben verwendeten Prozentsätze werden hier dargestellt, indem sie durch 100 geteilt werden.

 <path d="M size*0.5, (size*0.2) + radius          C size*0.5, size*0.5           x2,    size*0.5           x3,    size*0.8" > 

Bitte beachten Sie, dass die Verwendung von Prozentsätzen in unseren Formeln auf den ersten Blick optional erscheint, nur aufgrund meiner eigenen Meinung. Diese Werte werden jedoch nicht aus einer Laune heraus angewendet, sondern weil ihre Verwendung dazu beiträgt, Symmetrie und die richtigen Proportionen des Diagramms zu erreichen. Nachdem Sie ihre Rolle beim Diagramm gespürt haben, können Sie Ihre eigenen Prozentwerte ausprobieren und die Ergebnisse untersuchen, die durch Anwenden dieser Werte erzielt wurden.

Lassen Sie uns nun darüber sprechen, wie wir nach den Koordinaten x2 und x3 suchen werden. Mit ihnen können Sie dynamisch viele Kurven basierend auf dem index Elemente im entsprechenden Array erstellen.

Die Aufteilung des verfügbaren horizontalen Raums des Diagramms in gleiche Teile basiert auf der Anzahl der Elemente im Array. Infolgedessen erhält jedes Teil den gleichen Abstand entlang der x-Achse.

Die Formel, die wir ableiten, sollte anschließend mit einer beliebigen Anzahl von Elementen funktionieren. Aber hier werden wir mit einem Array experimentieren, das 5 Elemente enthält: [0,1,2,3,4] . Die Visualisierung eines solchen Arrays bedeutet, dass 5 Kurven gezeichnet werden müssen.

▍Finden dynamischer Koordinaten (x2 und x3)


Zuerst habe ich die size durch die Anzahl der Elemente geteilt, dh durch die Länge des Arrays. Ich habe diese variable distance . Es repräsentiert den Abstand zwischen zwei Elementen.

 distance = size/arrayLength // distance = 1000/5 = 200 

Dann ging ich um das Array herum und multiplizierte den Index jedes seiner Elemente ( index ) mit der distance . Der Einfachheit halber rufe ich einfach x sowohl den x2 Parameter als auch den x3 Parameter auf.

 //  x2  x3 x = index * distance 

Wenn Sie die erhaltenen Werte beim Erstellen des Diagramms anwenden, dh den oben berechneten x Wert sowohl für x2 als auch für x3 , sieht dies etwas seltsam aus.


Das Diagramm ist asymmetrisch

Wie Sie sehen können, befinden sich die Elemente in dem Bereich, in dem sie sich befinden sollten, aber das Diagramm hat sich als asymmetrisch herausgestellt. Es scheint, dass es im linken Teil mehr Elemente gibt als im rechten.

Jetzt muss der x3 Wert in der Mitte der entsprechenden Segmente liegen, deren Länge mithilfe der distance wird.

Um das Diagramm in die von mir benötigte Form zu bringen, habe ich einfach x Hälfte des distance addiert.

 x = index * distance + (distance * 0.5) 

Als Ergebnis fand ich den Mittelpunkt des distance und platzierte die x3 Koordinate darin. Außerdem habe ich zu der Form gebracht, dass wir die x2 Koordinate für Kurve Nr. 2 benötigen.


Symmetrisches Diagramm

Durch Hinzufügen des halben distance zu den Koordinaten x2 und x3 eignet sich die Berechnungsformel für diese Koordinaten zur Visualisierung von Arrays mit einer geraden und einer ungeraden Anzahl von Elementen.

▍ Bildmaskierung


Wir brauchen ein bestimmtes Bild, das oben im Diagramm innerhalb des Kreises angezeigt wird. Um dieses Problem zu lösen, habe ich eine Schnittmaske erstellt, die einen Kreis enthält.

 <defs>  <mask id="svg-mask">     <circle :r="radius"             :cx="halfSize"             :cy="topHeight"             fill="white"/>  </mask> </defs> 

Dann habe ich das Bild mit dem <image> -Tag des <image> <svg> <image> -Elements zum Anzeigen des Bildes mit dem oben erstellten <mask> -Element verknüpft, indem ich das mask Attribut des <image> -Elements verwendet habe.

 <image mask="url(#svg-mask)"      :x="(halfSize-radius)"      :y="(topHeight-radius)" ... > </image> 

Da wir versuchen, ein quadratisches Bild in ein rundes „Fenster“ einzupassen, habe ich die Position des Elements angepasst, indem ich den radius von den entsprechenden Parametern subtrahiert habe. Infolgedessen ist das Bild durch eine Maske in Form eines Kreises sichtbar.

Sammeln wir alles, worüber wir gesprochen haben, in einer Zeichnung. Dies wird uns helfen, das Gesamtbild des Arbeitsfortschritts zu sehen.


Daten zur Berechnung der Diagrammparameter

Erstellen eines dynamischen SVG-Bildes mit Vue.js.


Zu diesem Zeitpunkt haben wir die kubischen Bezier-Kurven herausgefunden und die zur Erstellung des Diagramms erforderlichen Berechnungen durchgeführt. Als Ergebnis können wir jetzt statische SVG-Diagramme erstellen. Wenn wir die Funktionen von SVG und Vue.js kombinieren, können wir Diagramme erstellen, die von Daten gesteuert werden. Statische Diagramme werden dynamisch.

In diesem Abschnitt überarbeiten wir das SVG-Diagramm und präsentieren es als eine Reihe von Vue-Komponenten. Wir werden auch SVG-Attribute an berechnete Eigenschaften anhängen und das Diagramm auf Datenänderungen reagieren lassen.

Darüber hinaus erstellen wir am Ende des Projekts eine Komponente, die ein Konfigurationsfenster ist. Diese Komponente wird verwendet, um Daten einzugeben, die an das Diagramm übertragen werden.

▍Binden von Daten an viewBox-Parameter


Beginnen wir mit der Anpassung des Koordinatensystems. Ohne dies können wir keine SVG-Bilder zeichnen. Die berechnete viewbox Eigenschaft gibt mithilfe der viewbox das zurück, was wir benötigen. Es gibt vier durch Leerzeichen getrennte Werte. All dies wird zum Wert des viewBox Attributs des <svg> -Elements.

 viewbox() {   return "0 0 " + this.size + " " + this.size; } 

In SVG ist der Name des viewBox Attributs bereits im viewBox geschrieben.

 <svg viewBox="0 0 1000 1000"> </svg> 

Um dieses Attribut korrekt an die berechnete Eigenschaft zu binden, habe ich den Attributnamen im Kebab-Stil .camel und den Modifikator .camel danach .camel . Mit diesem Ansatz ist es möglich, HTML zu "tricksen" und die Attributbindung korrekt zu implementieren.

 <svg :view-box.camel="viewbox">   ... </svg> 

Wenn Sie nun die size ändern size Diagramm unabhängig neu konfiguriert. Wir müssen das Layout nicht manuell ändern.

▍Berechnung von Kurvenparametern


Da die meisten Werte, die zum Erstellen der Kurven benötigt werden, auf der Grundlage einer einzelnen Variablen ( size ) berechnet werden, habe ich alle festen Koordinaten anhand der berechneten Eigenschaften ermittelt. Was wir hier "feste Koordinaten" nennen, wird auf der Grundlage der size berechnet und ändert sich danach nicht mehr und hängt nicht davon ab, wie viele Kurven das Diagramm enthalten wird.

Wenn Sie die size ändern, werden "feste Koordinaten" nachgezählt. Danach ändern sie sich erst bei der nächsten size . Vor diesem Hintergrund sind hier fünf Werte, die wir zum Zeichnen von Bezier-Kurven benötigen:

  • topHeight — size * 0.2
  • bottomHeight — size * 0.8
  • width — size
  • halfSize — size * 0.5
  • distance — size/arrayLength

Jetzt haben wir nur noch zwei unbekannte Werte - x2 und x3 . Die Formel zu ihrer Berechnung haben wir bereits abgeleitet:

 x = index * distance + (distance * 0.5) 

Um bestimmte Werte zu finden, müssen wir die Indizes der Array-Elemente in dieser Formel ersetzen.

Fragen wir uns nun, ob die berechnete Eigenschaft für uns richtig ist, um x zu finden. Beantworten Sie diese Frage kurz - nein, das reicht nicht.

Der berechneten Eigenschaft können keine Parameter übergeben werden. Tatsache ist, dass dies eine Eigenschaft ist, keine Funktion. Darüber hinaus bedeutet die Notwendigkeit, einen Parameter zu verwenden, um etwas zu berechnen, dass es keinen greifbaren Vorteil gibt, berechnete Eigenschaften in Bezug auf das Caching zu verwenden.

Bitte beachten Sie, dass es eine Ausnahme bezüglich des oben genannten Prinzips gibt. Es geht um Vuex. Wenn Sie Vuex-Getter verwenden, die Funktionen zurückgeben, können Sie ihnen Parameter übergeben.

In diesem Fall verwenden wir Vuex nicht. Aber auch in dieser Situation haben wir einige Möglichkeiten, dieses Problem zu lösen.

▍ Option Nummer 1


Sie können eine Funktion deklarieren, an die der index als Argument übergeben wird und die das benötigte Ergebnis zurückgibt. Dieser Ansatz sieht sauberer aus, wenn wir den von einer ähnlichen Funktion zurückgegebenen Wert an mehreren Stellen in der Vorlage verwenden.

 <g v-for="(item, i) in itemArray">  <path :d="'M' + halfSize + ','     + (topHeight+r) +' '+            'C' + halfSize + ','     + halfSize +' '+                     calculateXPos(i) + ',' + halfSize +' '+                  calculateXPos(i) + ',' + bottomHeight"  /> </g> 

Die Methode calculateXPos() führt bei jedem Aufruf Berechnungen durch. Diese Methode verwendet als Argument den Index des Elements - i .

 <script>  methods: {    calculateXPos (i)    {      return distance * i + (distance * 0.5)    }  } </script> 

Hier ist ein Beispiel für CodePen, das diese Lösung verwendet.


Bildschirm für die erste Anwendungsvariante

▍ Option Nummer 2


Diese Option ist besser als die erste. Wir können das kleine SVG-Markup extrahieren, das zum Erstellen der Kurve in eine separate kleine untergeordnete Komponente erforderlich ist, und den index als eine der Eigenschaften an diese übergeben.

Mit diesem Ansatz können Sie sogar die berechnete Eigenschaft verwenden, um x2 und x3 zu finden.

 <g v-for="(item, i) in items">    <cubic-bezier :index="i"                   :half-size="halfSize"                   :top-height="topHeight"                   :bottom-height="bottomHeight"                   :r="radius"                   :d="distance"     >     </cubic-bezier> </g> 

Diese Option gibt uns die Möglichkeit, den Code besser zu organisieren. Beispielsweise können wir eine weitere untergeordnete Komponente für die Maske erstellen:

 <clip-mask :title="title"           :half-size="halfSize"           :top-height="topHeight"                               :r="radius"> </clip-mask> 

▍Konfigurationsfenster



Konfigurationsfenster

Sie haben wahrscheinlich bereits das Konfigurationsfenster gesehen, das über die Schaltfläche in der oberen linken Ecke des Bildschirms des obigen Beispiels aufgerufen wird. In diesem Bereich können Sie dem Array auf einfache Weise Elemente hinzufügen und daraus entfernen. Gemäß den im Abschnitt "Option 2" beschriebenen Ideen habe ich eine untergeordnete Komponente für das Konfigurationsfenster erstellt. Dank dessen ist die Komponente der obersten Ebene sauber und gut lesbar. Infolgedessen sieht unser kleiner schöner Baum mit Vue-Komponenten ungefähr so ​​aus wie der folgende.


Projektkomponentenbaum

Möchten Sie einen Blick auf den Code werfen, der diese Version des Projekts implementiert? Wenn ja, schauen Sie hier .


Bildschirm für die zweite Anwendungsvariante

Projekt-Repository


Hier ist das GitHub-Repository des Projekts ("Option 2" ist hier implementiert). Ich glaube, es wird nützlich sein, wenn Sie es sich ansehen, bevor Sie mit dem nächsten Abschnitt fortfahren.

Hausaufgaben


Versuchen Sie, dasselbe Diagramm zu erstellen, das wir hier beschrieben haben, aber richten Sie es vertikal aus. Nutzen Sie die in diesem Artikel beschriebenen Ideen.

Wenn Sie der Meinung sind, dass dies eine einfache Aufgabe ist und es zum Erstellen eines solchen Diagramms ausreicht, die x und y Koordinaten zu vertauschen, haben Sie Recht. Da das hier betrachtete Projekt nicht als universell erstellt wurde, müssen Sie nach dem Ändern der Koordinaten an der gewünschten Stelle auch den Code bearbeiten, indem Sie einige Variablen und Methoden umbenennen.

Dank Vue.js kann unser einfaches Diagramm mit zusätzlichen Funktionen ausgestattet werden. Zum Beispiel Folgendes:

  • Sie können einen Mechanismus erstellen, mit dem Sie zwischen horizontalem und vertikalem Diagrammmodus wechseln können.
  • Kurven können versuchen zu animieren. Zum Beispiel mit GSAP.
  • Sie können die Eigenschaften der Kurven (z. B. Farbe und Linienbreite) im Konfigurationsfenster anpassen.
  • Sie können eine externe Bibliothek verwenden, um das Speichern von Diagrammen in einem beliebigen Grafikformat oder als PDF-Datei zu organisieren. Diese Materialien können für diejenigen heruntergeladen werden, die mit der Tabelle arbeiten.

Versuchen Sie diese Hausaufgaben. Und wenn Sie irgendwelche Probleme haben - unten erhalten Sie einen Link zu seiner Lösung.

Zusammenfassung


Das <path> -Element ist eine der leistungsstarken Funktionen von SVG. Mit diesem Element können Sie verschiedene Bilder mit hoher Genauigkeit erstellen. Hier haben wir herausgefunden, wie Bezier-Kurven strukturiert sind und wie sie in die Praxis umgesetzt werden können, um eigene Diagramme zu erstellen.

, , JavaScript-. Vue.js . , , , , DOM. , — .

, , , , , Vue.js SVG. — , Vue.js. — .

, - , , , — .

Liebe Leser! ?

Source: https://habr.com/ru/post/de463329/


All Articles