Alles in SVG verwenden und wiederverwenden… sogar Animationen!

Avatar of Mariana Beldi
Mariana Beldi am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Wenn Sie mit SVG und CSS-Animationen vertraut sind und oft damit arbeiten, gibt es hier einige Ideen, die Sie vor dem Start der Arbeit beachten sollten. Dieser Artikel beschäftigt sich damit, wie Sie Ihren Code mit dem <use>-Element, CSS-Variablen und CSS-Animationen erstellen und optimieren können.

Live-Demo

Teil 1: Das SVG <use>-Element

Wenn Sie ein Entwickler sind, der seinen Code gerne DRY (Don't Repeat Yourself) hält, oder ein großer Fan von Sass/CSS-Variablen sind, werden Sie dieses Tag wahrscheinlich mögen.

Nehmen wir an, Sie haben ein Element, das in Ihrer Grafik mehrmals wiederholt wird. Anstatt einen komplexen Teil Ihres Codes mehrmals in Ihrem SVG zu wiederholen, können Sie diesen Teil einmal definieren und ihn dann mit dem <use>-Element woanders in Ihrem Dokument klonen. Dies reduziert nicht nur eine enorme Menge an Code, sondern macht Ihre Auszeichnung auch einfacher und leichter zu manipulieren.

Um mit der Implementierung des <use>-Elements zu beginnen, gehen Sie zu Ihrem SVG und folgen Sie diesen Schritten

  1. Identifizieren Sie den Teil des Codes, den Sie klonen möchten
  2. Fügen Sie diesem Teil eine ID hinzu
  3. Verlinken Sie ihn innerhalb Ihres <use>-Tags wie folgt: <use xlink:href="#id"/>

Das war's! Ihr neuer Klon ist bereit, jetzt können Sie seine Attribute (z. B. x- und y-Position) ändern, um Ihren Bedürfnissen zu entsprechen.

Tauchen wir ein in ein sehr praktisches Beispiel

Ich möchte Ihnen einen echten Fall schildern, bei dem ich einen großen Würfel aus kleinen Würfeleinheiten animieren musste. (Stellen Sie sich den klassischen Rubik's Cube vor.)

Wir beginnen damit, die Würfeleinheit in SVG mit grundlegenden Formen und Transformationen zu zeichnen

<svg viewBox="-130 -20 300 100">
  <g id="cube">
    <rect width="21" height="24" transform="skewY(30)"/>
    <rect width="21" height="24" transform="skewY(-30) translate(21 24.3)"/>
    <rect width="21" height="21"  transform="scale(1.41,.81) rotate(45) translate(0 -21)"/>
  </g>
</svg>

Beachten Sie, dass die Formen in einem <g>-Element gruppiert sind, damit wir der gesamten Grafik die ID hinzufügen können.

Als Nächstes bauen wir einen größeren Würfel, indem wir diese Einheit klonen. Zuerst müssen wir den Würfel aus dem vorherigen Beispiel in das <defs>-Tag innerhalb des SVG einpacken. Im <defs>-Element können wir alles platzieren, was wir wiederverwenden möchten, sei es eine einzelne Form, eine Gruppe, ein Gradient… fast jedes SVG-Element. Sie werden nirgends gerendert, es sei denn, wir verwenden sie außerhalb dieses Tags.

Dann können wir die Einheit so oft wie gewünscht mit ihrer ID verknüpfen und die x- und y-Position bei jedem Klon wie folgt ändern

<use xlink:href="#cube" x="142" y="124"/>
<use xlink:href="#cube" x="100" y="124"/>
<!-- ... -->

Nun müssen wir jeden Würfel positionieren, wobei wir daran denken, dass das letzte Element vorne angezeigt wird. Danach ist unser erster großer Würfel fertig!

xlink:href ist seit SVG2 veraltet, aber es ist besser, es aus Kompatibilitätsgründen zu verwenden. In modernen Browsern können Sie einfach href verwenden, aber ich habe es in Safari getestet und zum Zeitpunkt der Erstellung funktioniert es dort nicht. Wenn Sie xlink:href verwenden, stellen Sie sicher, dass Sie diesen Namespace in Ihrem SVG-Tag einfügen: xmlns:xlink="http://www.w3.org/1999/xlink" (Sie benötigen ihn nicht, wenn Sie href verwenden möchten).

Teil 2: CSS-Variablen zur Anwendung unterschiedlicher Stile auf Ihre wiederverwendeten Grafiken

Ich habe eine Hauptfarbe für den Würfel gewählt, sowie einen helleren und einen dunkleren Farbton für die Seiten und eine Konturfarbe. Aber was ist, wenn wir einen zweiten Würfel in einer anderen Farbe haben möchten?

Wir können die Füllungen und Konturen durch CSS-Variablen ersetzen, um diese Attribute flexibler zu gestalten. So können wir die gleiche Würfeleinheit mit einer anderen Palette wiederverwenden (anstatt eine zweite Einheit mit unterschiedlichen Farben für einen zweiten Würfel zu definieren).

Warum nicht eine Klasse zum neuen Würfel hinzufügen und die Füllfarbe mit CSS ändern? Das werden wir tun, aber zuerst versuchen Sie, ein <use>-Element zu inspizieren. Sie werden feststellen, dass es im Shadow DOM gerendert wird, was bedeutet, dass es nicht anfällig für Skripte und Stile ist, wie Elemente im normalen DOM. Welche Werte Sie auch immer in der Grafik innerhalb von <defs> definieren, werden von allen seinen Instanzen geerbt, und Sie können diese nicht mit CSS überschreiben. Aber wenn Sie diese Werte durch Variablen ersetzen, können Sie sie in CSS steuern.

In unserer Würfeleinheit gehen wir jede Seite durch und ersetzen die Füll- und Konturwerte durch semantische Variablennamen.

Zum Beispiel kann dieses

<rect fill="#00affa" stroke="#0079ad" />

…ersetzt werden durch dieses

<rect fill="var(--mainColor)" stroke="var(--strokeColor)" />

Von hier aus müssen wir das SVG duplizieren, um einen zweiten Würfel zu bauen. Wir müssen jedoch <defs> nicht duplizieren, wenn wir beide im selben Dokument behalten. Wir können jedem SVG eine Klasse hinzufügen und die Farbpalette über CSS steuern, indem wir die Werte der Variablen neu definieren.

Lassen Sie uns eine Palette für den blauen Würfel und eine weitere für den rosa Würfel erstellen

.blue-cube {
  --mainColor: #009CDE;
  --strokeColor: #0079ad;
  --lightColor: #00affa;
  --darkColor: #008bc7;
}

.pink-cube {
  --mainColor: #de0063;
  --strokeColor: #ad004e;
  --lightColor: #fa0070;
  --darkColor: #c7005a;
}

Auf diese Weise können wir beliebig viele Würfel hinzufügen und alle Farben von einem Ort aus ändern.

Teil 3: Animationen wiederverwenden

Die Idee für diese Instanz ist es, die Würfel beim Hovern zu zerlegen – so etwas wie eine explosive Ansicht, bei der sich einige Teile beim Überfahren der Würfel mit der Maus vom Zentrum weg bewegen.

Beginnen wir mit der Definition zweier Bewegungen, einer für jede Achse: move Y und move X. Indem wir die Animationen in Bewegungen aufteilen, können wir sie bei jedem Würfel wiederverwenden. Die Animationen bestehen darin, den Würfel von seiner Ausgangsposition um 30 oder 50 Pixel in eine Richtung zu bewegen. Dazu können wir eine Transformations-Translation (X oder Y) verwenden. Zum Beispiel

@keyframes moveX {
  to { transform: translateX(-35px);  }
}

Aber wenn wir diese Animation wiederverwenden wollen, ist es besser, den numerischen Wert durch eine Variable zu ersetzen, so wie hier

@keyframes moveX {
  to { transform: translateX(var(--translate, 35px)); }
}

Wenn die Variable nicht definiert ist, beträgt der Standardwert 35px.

Jetzt brauchen wir mindestens eine Klasse, die an die Animation gebunden wird. In diesem Fall benötigen wir jedoch zwei Klassen, um Würfel auf der x-Achse zu bewegen: .m-left und .m-right.

.m-left, .m-right { 
  animation: 2s moveX alternate infinite; 
}

Damit sich der Würfel nach links bewegt, benötigen wir einen negativen Wert, aber wir können auch eine andere Zahl deklarieren. Wir können unsere Variable wie folgt *innerhalb* der Klasse .m-left definieren

.m-left { --translate: -50px; }

Was hier passiert ist, dass wir deklarieren, dass, wenn wir die Klasse .m-left zu einem Element hinzufügen, dieses die Animation moveX (die in den @keyframes definiert ist) abspielt, die zwei Sekunden dauern wird, um in der x-Achse zu übersetzen und eine neue Position von -50 Pixel links zu erreichen. Dann wechselt die Animation die Richtung, so dass sie von der letzten Position ausgeht und zwei weitere Sekunden benötigt, um in ihren ursprünglichen Zustand zurückzukehren. Und so weiter, da es eine Endlosschleife ist.

Wir können eine weitere Variable für die Klasse .m-right deklarieren, aber wenn wir das nicht tun, denken Sie daran, dass sie die anfangs deklarierten 35px verwendet.

Der Standardwert von animation-play-state ist running, aber vielleicht wollen wir nicht, dass sich die Würfel die ganze Zeit bewegen. Das wäre sehr ablenkend und störend auf einer Website mit benachbarten Inhalten. Versuchen wir also, die Animation nur beim Hovern abzuspielen, indem wir dies hinzufügen

svg:hover .m-left {
  animation: 2s moveX alternate infinite;
}

Sie können es selbst ausprobieren und werden feststellen, dass die Animation jedes Mal, wenn wir die Maus aus dem Würfel bewegen, super schnell in den Ausgangszustand springt. Um dies zu vermeiden, können wir am Ende der Animation-Kurzschreibweise den Wert paused hinzufügen

.m-left {
  animation: 2s moveX alternate infinite paused;
}

Jetzt ist die Animation pausiert, wird aber beim Hovern ausgeführt, indem diese CSS-Zeile hinzugefügt wird

svg:hover * { 
  animation-play-state: running; 
}

Wir können jede Klasse verschiedenen Elementen in SVG zuweisen. Beim ersten blauen Würfel bewegen wir einzelne Würfel; beim zweiten wenden wir diese Klassen auf Gruppen von Würfeln an.

Ein letztes Ding…

Erst später erkannte ich, dass ich eine einzelne Einheit wiederverwenden konnte, um sie alle zu bauen. Ich habe am kleinen Würfel gearbeitet, um ihn isometrisch genug zu machen, damit er sich leicht an die anderen daneben ausrichten lässt. An diesem Punkt war meine Einheit ein <path>, aber ich entschied mich, sie durch SVG-Formen zu ersetzen, um den Code zu reduzieren und eine sauberere Auszeichnung zu erhalten.

Ich habe gelernt, dass es besser ist, sich Zeit zu nehmen, um zu analysieren, was mit SVG gemacht werden kann, bevor man jede einzelne Form zeichnet und mit einer riesigen Menge Code umgeht. Es mag am Anfang mehr Zeit kosten, aber auf lange Sicht wird es Ihnen viel Zeit und Mühe sparen.