Heim >Web-Frontend >CSS-Tutorial >So erstellen Sie ein animiertes Diagramm verschachtelter Quadrate mit Masken

So erstellen Sie ein animiertes Diagramm verschachtelter Quadrate mit Masken

Lisa Kudrow
Lisa KudrowOriginal
2025-03-18 11:03:23835Durchsuche

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:

Was wir machen

Ohne Interaktivität ist das Erstellen dieses Designs ziemlich einfach. Eine Möglichkeit, dies zu tun, besteht darin, Elemente (z. B. SVG -Elemente oder sogar HTML-Divs) in abnehmenden Größen zu stapeln, bei denen alle ihre unteren linken Ecken den gleichen Punkt berühren.

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 mit und Elementen. Wenn Sie völlig neu für Masken sind, sind Sie am richtigen Ort. Dies ist ein Artikel auf Einführungsebene. Wenn Sie mehr gewürzt sind, ist dieser Ausschnittseffekt vielleicht ein Trick, den Sie mitnehmen können.

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 kann einschüchternd sein oder sogar chaotisch werden. Wir arbeiten also mit „einfacheren“ Elementen, um die gleichen Formen und Effekte zu erhalten.

So müssten wir beispielsweise die größte blaue Form mit einem darstellen.

 <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.

Die Grundlagen des Diagramms

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>

Ermittlung des höchsten Wertes

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.

Berechnung der Dimension der Rechtecke

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

Erstellen und Einsetzen der DOM -Elemente

Was übrig bleibt, hat mit Dom -Manipulation zu tun. Wir müssen die und die fünf -Elemente erstellen, ihre Attribute festlegen und an die DOM anhängen. Wir können dies alles mit den Basic CreateLementns, SetAttribute und den AppendChild -Funktionen tun.

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.

Ausschnittsrechtecke

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.

Maskierung 101

Eine Maske ist etwas, das Sie definieren und später für ein Element anwenden. Typischerweise ist die Maske in das -Element, zu dem sie gehört, eingeführt. Und im Allgemeinen sollte es eine eindeutige ID haben, da wir sie verweisen müssen, um die Maske auf ein Element anzuwenden.

 <svg>
  <mask>
    
  </mask>
</svg>

Im -Tag setzen wir die Formen ein, die als tatsächliche Masken dienen. Wir wenden das Maskenattribut auch auf die Elemente an.

 <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.

Die weiße Füllung

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.

Die schwarze Füllung

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.

Die graue Füllung

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.

Das letzte Stück

Folgendes haben wir bisher über Masken behandelt und gelernt:

  • Das Element in der steuert die Dimension des maskierten Bereichs.
  • Wir können den Inhalt des maskierten Bereichs sichtbar, unsichtbar oder transparent machen.

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 Elemente. Wir müssen sie übereinander stapeln:

 <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 ist die Dimension des größten Elements und das größte Element ist mit Schwarz gefüllt. Das bedeutet, dass alles unter diesem Bereich unsichtbar ist. Und alles unter dem kleineren Rechteck ist sichtbar.

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.

Erzeugen der Masken

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, ...

Das Endergebnis

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 -Element, um die Ausschnittsfläche jedes Quadrats zu zeichnen.

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn