Heim >Web-Frontend >CSS-Tutorial >So erstellen Sie ein animiertes Diagramm verschachtelter Quadrate mit Masken
Wir haben viele bekannte Diagrammtypen: Bar, Donut, Linie, Kuchen, Sie nennen es. Alle beliebten Diagrammbibliotheken unterstützen diese. Dann gibt es die Diagrammtypen, die nicht einmal einen Namen haben. Schauen Sie sich dieses Dreamt-up-Diagramm mit gestapelten (verschachtelten) Quadraten an, mit denen sich die relativen Größen visualisieren kann oder wie unterschiedliche Werte miteinander verglichen werden:
Ohne Interaktivität ist das Erstellen dieses Designs ziemlich einfach. Eine Möglichkeit, dies zu tun, besteht darin, Elemente (z. B. SVG
Aber die Dinge werden schwieriger, sobald wir etwas Interaktivität einführen. So sollte es sein: Wenn wir unsere Maus über eine der Formen bewegen, möchten wir, dass die anderen verblassen und wegziehen.
Wir werden diese unregelmäßigen Formen mit Rechtecken und Masken erstellen - buchstäblich
Bevor wir beginnen, fragen Sie sich möglicherweise, ob eine bessere Alternative zu SVG zur Verwendung benutzerdefinierter Formen. Das ist definitiv eine Möglichkeit! Das Zeichnen von Formen mit einem
So müssten wir beispielsweise die größte blaue Form mit einem
<svg viewbox="0 0 320 320" width="320" height="320"> <pfad d="M320 0H0V56H264V320H320V0Z" fill="#264653"></pfad> </svg>
Wenn der 0H0V56… für Sie keinen Sinn ergibt, finden Sie in der SVG -Pfadsyntax: Eine illustrierte Anleitung “, um eine gründliche Erläuterung der Syntax zu erhalten.
Bei einem solchen Datensatz:
Geben Sie DataSetEntry = {ein Etikett: String; Wert: Zahl; }; type DataSet = DataSetEentry []; const rawdataset: dataset = [ {Label: 'Bad', Wert: 1231}, {Label: 'Anfang', Wert: 6321}, {label: 'entwickeln', Wert: 10028}, {label: 'vervollständigt', Wert: 12123}, {Label: 'Exemplary', Wert: 2120} ];
… Wir wollen mit einem SVG wie folgt enden:
<svg viewbox="0 0 320 320" width="320" height="320"> <rect width="320" height="320" y="0" fill="..."> </rect> <rect width="264" height="264" y="56" fill="..."> </rect> <rect width="167" height="167" y="153" fill="..."> </rect> <rect width="56" height="56" y="264" fill="..."> </rect> <rect width="32" height="32" y="288" fill="..."> </rect> </svg>
Es wird in einem Moment deutlich, warum wir den höchsten Wert brauchen. Wir können die math.max () verwenden, um sie zu bekommen. Es akzeptiert eine beliebige Anzahl von Argumenten und gibt den höchsten Wert in einem Satz zurück.
const dataSthighestValue: number = math.max ( ... rawdataset.map ((Eintrag: DataSetEntry) => Eintrag.Value) );
Da wir einen kleinen Datensatz haben, können wir nur sagen, dass wir 12123 erhalten.
Wenn wir uns das Design ansehen, deckt das Rechteck, das den höchsten Wert (12123) darstellt, den gesamten Bereich des Diagramms ab.
Wir haben willkürlich 320 für die SVG -Abmessungen ausgewählt. Da unsere Rechtecke Quadrate sind, sind Breite und Höhe gleich. Wie können wir 12123 gleich 320 erreichen? Wie wäre es mit den weniger „besonderen“ Werten? Wie groß ist das 6321 Rechteck?
Auf andere Weise gefragt, wie wir eine Zahl von einem Bereich ([0, 12123]) auf einen anderen ([0, 320]) zuordnen? Oder wie skalieren wir in mathematischeren Begriffen eine Variable zu einem Intervall von [A, B]?
Für unsere Zwecke werden wir die Funktion wie diese implementieren:
const remapValue = ( Wert: Zahl, Frommin: Nummer,, Frommax: Nummer, Tomin: Zahl, Tomax: Nummer ): number => { return ((value - frommin) / (frommax - frommin)) * (tomax - tomin) tomin; }; RemapValue (1231, 0, 12123, 0, 320); // 32 RemapValue (6321, 0, 12123, 0, 320); // 167 RemapValue (12123, 0, 12123, 0, 320); // 320
Da wir Werte in unserem Code auf denselben Bereich zuordnen, können wir eine Wrapper -Funktion erstellen, anstatt die Mindest- und Maximums immer wieder zu übergeben:
const valueremapper = ( Frommin: Nummer,, Frommax: Nummer, Tomin: Zahl, Tomax: Nummer ) => { return (Wert: Nummer): Nummer => { Return RemapValue (Wert, Fromin, Fromax, Tomin, Tomax); }; }; const remapdatasetvaluetosvgdimension = valueremapper ( 0,, DataSethighestValue, 0,, svgdimension );
Wir können es so verwenden:
remapdatasetvaluetosvgdimension (1231); // 32 remapdatasetvaluetosvgdimension (6321); // 167 remapdatasetvaluetosvgdimension (12123); // 320
Was übrig bleibt, hat mit Dom -Manipulation zu tun. Wir müssen die
Beachten Sie, dass wir die CreateLementns anstelle der allgemeineren CreateLement verwenden. Dies liegt daran, dass wir mit einem SVG arbeiten. HTML- und SVG -Elemente haben unterschiedliche Spezifikationen, sodass sie unter einen anderen Namespace -URI fallen. Es kommt einfach vor, dass die CreateLement den HTML -Namespace bequem verwendet! Um ein SVG zu erstellen, müssen wir diese ausführliche sein:
document.createelementns ('http://www.w3.org/2000/svg', 'svg') als SVGSVGElement;
Sicher können wir eine weitere Helferfunktion erstellen:
const crectesVgNSelement = (Element: String): svgelement => { return document.createelementns ('http://www.w3.org/2000/svg', Element); };
Wenn wir die Rechtecke an das DOM anhängen, müssen wir auf ihre Bestellung achten. Andernfalls müssten wir den Z-Index explizit angeben. Das erste Rechteck muss das größte sein, und das letzte Rechteck muss das kleinste sein. Am besten sortieren Sie die Daten vor der Schleife.
const data = rawdataset.sort ( (A: DataSetEntry, B: DataSetEntry) => B.Value - A.Value ); Data.foreach ((d: DataSetEntry, Index: Nummer) => { const rect: svGrectElement = createsVGNSelement ('rechtex') als svGrectelement; const rectdimension: number = remapdatasetvaluetosvgdimension (d.value); rect.setAttribute ('width', "$ {rectdimension}`); rect.setAttribute ('Höhe', "$ {rectdimension}`); rect.setAttribute ('y', "$ {svgdimension - rectdimension}`); svg.appendchild (rect); });
Das Koordinatensystem beginnt von der oberen Links. Hier ist der [0, 0]. Wir werden immer die Rechtecke von der linken Seite zeichnen. Das X -Attribut, das die horizontale Position steuert, ist standardmäßig auf 0, sodass wir sie nicht festlegen müssen. Das y -Attribut steuert die vertikale Position.
Um den visuellen Eindruck zu vermitteln, dass alle Rechtecke aus demselben Punkt stammen, der ihre unteren linken Ecken berührt, müssen wir die Rechtecke sozusagen nach unten drücken. Durch wie viel? Die genaue Menge, die das Rechteck nicht füllt. Und dieser Wert ist der Unterschied zwischen der Dimension des Diagramms und dem jeweiligen Rechteck. Wenn wir alle Teile zusammenfügen, haben wir Folgendes:
Mit CSS haben wir den Code für die Animation bereits zu dieser Demo hinzugefügt.
Wir müssen unsere Rechtecke in unregelmäßige Formen verwandeln, die wie die Nummer sieben aussehen oder den Buchstaben L 180 Grad gedreht.
Wenn wir uns auf die „fehlenden Teile“ konzentrieren, können wir sehen, dass sie Ausschnitte der gleichen Rechtecke, mit denen wir bereits arbeiten, ausschneiden.
Wir wollen diese Ausschnitte verbergen. So werden wir die L-F-F-Form, die wir wollen.
Eine Maske ist etwas, das Sie definieren und später für ein Element anwenden. Typischerweise ist die Maske in das
<svg> <mask> </mask> </svg>
Im
<svg> <mask> </mask> <rect mask="url (#mycleverlyNamedmask)"> </rect> </svg>
Dies ist nicht der einzige Weg, um eine Maske zu definieren oder anzuwenden, aber für diese Demo ist dies der einfachste Weg. Lassen Sie uns ein wenig experimentieren, bevor wir einen Code schreiben, um die Masken zu generieren.
Wir sagten, dass wir die Ausschnittsbereiche abdecken wollen, die den Größen der vorhandenen Rechtecke entsprechen. Wenn wir das größte Element nehmen und das vorherige Rechteck als Maske anwenden, erhalten wir diesen Code:
<svg viewbox="0 0 320 320" width="320" height="320"> <mask> <rect width="264" height="264" y="56" fill=""> </rect> </mask> <rect width="320" height="320" y="0" fill="#264653" mask="url (#themask)"> </rect> </svg>
Das Element in der Maske benötigt einen Füllwert. Was sollte das sein? Wir werden ganz unterschiedliche Ergebnisse sehen, die auf dem von uns ausgewählten Füllwert (Farbe) basieren.
Wenn wir einen weißen Wert für die Füllung verwenden, erhalten wir Folgendes:
Jetzt ist unser großes Rechteck die gleiche Dimension wie das maskierende Rechteck. Nicht genau das, was wir wollten.
Wenn wir stattdessen einen schwarzen Wert verwenden, sieht es so aus:
Wir sehen nichts. Das liegt daran, dass das, was mit Schwarz gefüllt ist, unsichtbar wird. Wir steuern die Sichtbarkeit von Masken mit weißen und schwarzen Füllungen. Die gestrichelten Linien sind als visuelle Hilfe zur Verweise auf die Abmessungen des unsichtbaren Bereichs.
Verwenden wir nun etwas zwischen Weiß und Schwarz, sagen wir Gray:
Es ist weder vollständig undurchsichtig noch fest; Es ist transparent. Jetzt wissen wir also, dass wir hier den „Grad der Sichtbarkeit“ kontrollieren können, indem wir etwas anderes als weiße und schwarze Werte verwenden, was ein guter Trick ist, um in unseren Hintertaschen zu bleiben.
Folgendes haben wir bisher über Masken behandelt und gelernt:
Wir haben nur eine Form für die Maske verwendet, aber wie bei jedem Allzweck -HTML -Tag können wir so viele Kinderelemente dort nisten, wie wir wollen. Tatsächlich ist der Trick, das zu erreichen, was wir wollen, zwei SVG
<svg viewbox="0 0 320 320" width="320" height="320"> <mask> <rect width="320" height="320" y="0" fill="???"> </rect> <rect width="264" height="264" y="56" fill="???"> </rect> </mask> <rect width="320" height="320" y="0" fill="#264653" mask="url (#maskw320)"> </rect> </svg>
Einer unserer maskierenden Rechtecke ist mit Weiß gefüllt; Der andere ist mit Schwarz gefüllt. Auch wenn wir die Regeln kennen, probieren wir die Möglichkeiten aus.
<mask> <rect width="320" height="320" y="0" fill="schwarz"> </rect> <rect width="264" height="264" y="56" fill="White"> </rect> </mask>
Die
Lassen Sie uns nun Dinge machen, bei denen das schwarze Rechteck oben ist:
<mask> <rect width="320" height="320" y="0" fill="White"> </rect> <rect width="264" height="264" y="56" fill="schwarz"> </rect> </mask>
Das wollen wir!
Alles unter dem größten weiß gefüllten Rechteck ist sichtbar, aber das kleinere schwarze Rechteck befindet sich darüber (näher an uns auf der Z-Achse) und maskiert diesen Teil.
Nachdem wir wissen, was wir tun müssen, können wir die Masken relativ leicht erstellen. Es ist ähnlich wie wir die farbigen Rechtecke in erster Linie erzeugt haben - wir erstellen eine sekundäre Schleife, in der wir die Maske und die beiden Rektionen erstellen.
Anstatt die Rektionen direkt an die SVG anzugreifen, fügen wir diesmal die Maske hinzu:
Data.foreach ((d: DataSetEntry, Index: Nummer) => { const mask: const rectdimension: number = remapdatasetvaluetosvgdimension (d.value); const rect: svGrectElement = createsVGNSelement ('rechtex') als svGrectelement; rect.setAttribute ('width', "$ {rectdimension}`); // ... Setzen Sie den Rest der Attribute ... mask.setattribute ('id', `maskw $ {rectdimension.tofixed ()}`); Mask.AppendChild (rect); // ... Erstellen und Festlegen der Attribute für das kleinere Rechteck ... Svg.AppendChild (Maske); }); Data.foreach ((d: DataSetEntry, Index: Nummer) => { // ... unser Code, um die farbigen Rechtecke zu generieren ... });
Wir könnten den Index als ID der Maske verwenden, aber dies scheint mir zumindest eine lesbare Option zu sein:
mask.setattribute ('id', `maskw $ {rectdimension.tofixed ()}`); // Maskw320, Masw240, ...
Was das Hinzufügen des kleineren Rechtecks in der Maske hinzufügen, haben wir einen einfachen Zugriff auf den Wert, den wir benötigen, da wir zuvor die Rechteckwerte vom höchsten bis niedrigsten bestellt haben. Das bedeutet, dass das nächste Element in der Schleife das kleinere Rechteck ist, auf das wir verweisen sollten. Und das können wir durch seinen Index tun.
// ... vorheriger Teil, in dem wir die Maske und das Rechteck erstellt haben ... const smalleRectIndex = Index 1; // Es gibt keinen nächsten, wenn wir am kleinsten sind if (data [smallErectIndex]! == undefiniert) { const smalleRectDimension: Zahl = remapdatasetvaluetosvgDimension ( Daten [smalleRectIndex] .Value ); const smalleRect: svGrectElement = createVGnSelement ( "RECHT" ) als SvGrectelement; // ... Einstellen der Rechteckattribute ... Mask.AppendChild (smalleRect); } Svg.AppendChild (Maske);
Was übrig bleibt, ist, das Maskenattribut dem farbigen Rechteck in unserer ursprünglichen Schleife hinzuzufügen. Es sollte dem Format übereinstimmen, das wir ausgewählt haben:
rect.setAttribute ('mask', `url (#maskw $ {rectdimension.tofixed ()})`); // Maskw320, Maskw240, ...
Und wir sind fertig! Wir haben erfolgreich ein Diagramm erstellt, das aus verschachtelten Quadraten besteht. Es kommt sogar bei Mausschwebede auseinander. Und alles, was es brauchte, war einige SVG mit dem
Das obige ist der detaillierte Inhalt vonSo erstellen Sie ein animiertes Diagramm verschachtelter Quadrate mit Masken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!