Wie ich einen Generator für SVG-Loader mit Sass und SMIL-Optionen erstellt habe

Avatar of Mariana Beldi
Mariana Beldi am

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

Während ich Vue.js lernte, begann ich, kostenlose Web-Tools zu entwickeln, die die Erkundung von SVG beinhalteten, mit dem Ziel, etwas über beides zu lernen! Werfen wir einen Blick auf eines dieser Tools: einen Generator, der SVG-Loader erstellt und Ihnen die Wahl zwischen SMIL- oder Sass-Animation, verschiedenen Stilen, Farben, Formen und Effekten gibt. Sie können sogar benutzerdefinierte Pfade oder Text einfügen und dann die endgültige SVG herunterladen, den Code kopieren oder eine Demo bei CodePen öffnen.

Wie es begann

Drei Zufälle führten mich dazu, einen Generator für SVG-Loader zu bauen.

Zufall 1: Sarah Drasners Buch

Das erste Mal, als ich von Sass-Schleifen hörte, war in Sarah Drasners Buch SVG Animations. Sie zeigt, wie Animationen mit einer Sass-Funktion gestaffelt werden (wie in Kapitel 6: „Animating Data Visualizations“).

Dieses Kapitel und die Möglichkeiten von Sass-Schleifen haben mich inspiriert.

Zufall 2: Ein GIF

Zu dieser Zeit wurde ich gebeten, ein „Loader“-Element zu replizieren, ähnlich wie bei Apples altem Klassiker.

A round segmented spinner where each segment fades in and out in succession to create a circling effect.
Dies ist ein Mockup des Loaders, den ich erstellen sollte.

Ich habe mich auf Sarahs Beispiel bezogen, um dies zu realisieren. Dies ist der Sass-Loop-Code, den ich verwendet habe:

@for $i from 1 to 12 {
  .loader:nth-of-type(#{$i}) {
    animation: 1s $i * 0.08s opacityLoader infinite;
  }
}
@keyframes opacityLoader {
 to { opacity: 0; }
}

Dies definiert eine Variable für eine Zahl (i) von 1 bis 12, die die Verzögerung der Animation mit jedem :nth-child-Element erhöht. Es war der perfekte Anwendungsfall, um so viele Elemente zu animieren, wie ich wollte, mit nur zwei Zeilen Sass, was mir CSS-Deklarationen für jede benötigte Verzögerung ersparte. Dies ist dieselbe Animation, aber in Vanilla CSS geschrieben, um den Unterschied zu zeigen

.loader:nth-of-type(1) {
  animation: 1s 0.08s opacityLoader infinite;
}
.loader:nth-of-type(2) {
  animation: 1s 0.16s opacityLoader infinite;
}

/* ... */

.loader:nth-of-type(12) {
  animation: 1s 0.96s opacityLoader infinite;
}
@keyframes opacityLoader {
  to { opacity: 0; }
}

Zufall 3: Eine Idee

Mit diesen Dingen, die mir durch den Kopf gingen, hatte ich die Idee für eine Galerie von Loadern, bei der jeder Loader aus derselben Sass-Schleife besteht. Ich habe immer Schwierigkeiten, solche Dinge online zu finden, also dachte ich, es könnte für andere nützlich sein, ganz zu schweigen von mir selbst.

Ich hatte bereits so etwas als persönliches Projekt erstellt, und deshalb habe ich einen Loader-Generator erstellt. Lassen Sie mich wissen, wenn Sie Fehler darin finden!

Ein Loader, zwei Ausgaben

Ich wurde durch meine eigenen Entwicklerfähigkeiten blockiert, als ich einen Generator erstellte, der die richtige Sass-Ausgabe liefert. Ich beschloss, einen anderen Animationsansatz mit SMIL-Animationen auszuprobieren, und das habe ich dann auch gemacht.

Aber dann erhielt ich Hilfe (danke, ekrof!) und Sass funktionierte doch noch.

Also habe ich beide Optionen zum Generator hinzugefügt. Ich fand es eine Herausforderung, beide Sprachen dasselbe Ergebnis erzielen zu lassen. Tatsächlich erzeugen sie manchmal unterschiedliche Ergebnisse.

SMIL vs. CSS/Sass

Ich habe dabei viel über SMIL- und CSS/Sass-Animationen gelernt. Dies sind einige der wichtigsten Erkenntnisse, die mir auf meinem Weg zur Erstellung des Generators geholfen haben

  • SMIL benötigt keine externen Ressourcen. Es animiert SVG direkt über Präsentationsattribute im SVG-Markup. Das können weder CSS noch Sass tun.
  • SMIL-Animationen bleiben erhalten, wenn eine SVG als Bild oder als Hintergrundbild eingebettet wird. Es ist möglich, einen CSS-<style>-Block direkt in die SVG einzufügen, aber natürlich nicht so einfach mit Sass. Deshalb gibt es die Option, die tatsächliche SVG-Datei herunterzuladen, wenn die SMIL-Option im Generator ausgewählt wird.
  • SMIL-Animationen wirken etwas flüssiger. Ich konnte den Grund dafür nicht finden (wenn jemand tiefere Informationen dazu hat, bitte teilen!). Ich dachte, es hätte mit GPU-Beschleunigung zu tun, aber es scheint, dass beide die gleiche Animations-Engine verwenden.
Two spinners, one left and one right. They are both red and consist of circles that fade in and out in succession as an animated GIF.
SMIL (links) und Sass (rechts)

Sie bemerken vielleicht einen Unterschied im Chaining (Aneinanderreihung) der Animationen zwischen beiden Sprachen

  • Ich habe additive="sum" in SMIL verwendet, um Animationen nacheinander hinzuzufügen. Dies stellt sicher, dass jeder neue Animationseffekt den vorherigen Animationseffekt nicht überschreibt.
  • Das bedeutet, dass in CSS/Sass das W3C angibt, dass [wenn] mehrere Animationen versuchen, dieselbe Eigenschaft zu ändern, dann gewinnt die Animation, die am Ende der Liste der Namen steht.

Deshalb kann die Reihenfolge, in der Animationen angewendet werden, die Sass-Ausgabe ändern.

Arbeiten mit Transformationen

Die Arbeit mit Transformationen im Styling des Loaders war ein großes Problem. Ich hatte transform: rotate inline auf jede Form angewendet, da dies eine einfache Möglichkeit ist, sie im Kreis nebeneinander zu platzieren und sie zum Zentrum hin auszurichten.

<svg>
  <!-- etc. -->
  <use class="loader" xlink:href="#loader" transform="rotate(0 50 50)" />
  <use class="loader" xlink:href="#loader" transform="rotate(30 50 50)" />
  <use class="loader" xlink:href="#loader" transform="rotate(60 50 50)" />
  <!-- etc. -->
</svg>

Ich konnte einen type in SMIL mit <animateTransform> deklarieren (z. B. scale oder translate), um diese spezifische Transformation zur ursprünglichen Transformation jeder Form hinzuzufügen

<animateTransform
  attributeName="transform"
  type="translate"
  additive="sum"
  dur="1s"
  :begin="`${i * 0.08}s`"
  repeatCount="indefinite"
  from="0 0"
  to="10"
/>

Aber stattdessen überschrieb transform in CSS jede vorherige Transformation, die auf das Inline-SVG angewendet wurde. Mit anderen Worten, die ursprüngliche Position wurde auf 0 zurückgesetzt und zeigte ein sehr anderes Ergebnis als das, was SMIL erzeugte. Das bedeutete, dass die Animationen egal was passierte, identisch aussahen.

The same two red spinners as before but with different results. The SMIL version on the left seems to work as expected but the Sass one on the right doesn't animate in a circle like it should.

Die (nicht sehr schöne) Lösung, um Sass SMIL ähnlich zu machen, war, jede Form in ein Gruppenelement (<g>) zu platzieren und die Inline-Rotation auf die Gruppen anzuwenden und die Animation auf die Formen. Auf diese Weise wird die Inline-Transformation nicht von der Animation beeinflusst.

<svg>
  <!-- etc. -->
  <g class="loader" transform="rotate(0 50 50)">
    <use xlink:href="#loader" />
  </g>
  <g class="loader" transform="rotate(30 50 50)">
    <use xlink:href="#loader" />
  </g>
  <!-- etc. -->
</svg>

Jetzt haben beide Sprachen ein sehr ähnliches Ergebnis.

Die Technologie, die ich verwendet habe

Ich habe Vue.js und Nuxt.js verwendet. Beide haben großartige Dokumentationen, aber es gibt spezifischere Gründe, warum ich sie gewählt habe.

Ich mag Vue aus vielen Gründen

  • Vue kapselt HTML, CSS und JavaScript als „Single File Component“, bei dem der gesamte Code in einer einzigen Datei liegt, mit der es einfacher ist zu arbeiten.
  • Die Art und Weise, wie Vue HTML- oder SVG-Attribute bindet und dynamisch aktualisiert, ist sehr intuitiv.
  • HTML und SVG erfordern keine zusätzlichen Transformationen (wie die Umwandlung des Codes in JSX-kompatibel).

Was Nuxt betrifft

  • Es hat ein schnelles Boilerplate, das Ihnen hilft, sich auf die Entwicklung statt auf die Konfiguration zu konzentrieren.
  • Es gibt automatische Routingfunktionen und es unterstützt den automatischen Import von Komponenten.
  • Es ist eine gute Projektstruktur mit Seiten, Komponenten und Layouts.
  • Es ist einfacher für SEO zu optimieren, dank Meta-Tags.

Schauen wir uns ein paar Beispiel-Loader an

Was mir am Endergebnis gefällt, ist, dass der Generator kein Ein-Trick-Pony ist. Es gibt keine einzige Methode, ihn zu verwenden. Da er sowohl SMIL als auch CSS/Sass ausgibt, gibt es mehrere Möglichkeiten, einen Loader in Ihr eigenes Projekt zu integrieren.

Laden Sie die SMIL-SVG herunter und verwenden Sie sie als Hintergrundbild in CSS

Wie ich bereits erwähnt habe, bleiben SMIL-Funktionen erhalten, wenn eine SVG als Hintergrundbilddatei verwendet wird. Laden Sie also einfach die SVG vom Generator herunter, laden Sie sie auf Ihren Server hoch und referenzieren Sie sie in CSS als Hintergrundbild.

Ähnlich könnten wir die SVG als Hintergrundbild eines Pseudo-Elements verwenden

Fügen Sie die SVG direkt in das HTML-Markup ein

Die SVG muss kein Hintergrundbild sein. Es ist schließlich nur Code. Das bedeutet, dass wir den Code vom Generator einfach in unser eigenes Markup einfügen und SMIL seine Arbeit machen lassen können.

Verwenden Sie eine Sass-Schleife auf der Inline-SVG

Das ist es, was mich ursprünglich inspiriert hat, aber ich bin auf einige Hindernisse gestoßen. Anstatt CSS-Deklarationen für jede Animation zu schreiben, können wir die Sass-Schleife verwenden, die vom Generator erzeugt wird. Die Schleife zielt auf eine .loader-Klasse ab, die bereits auf die ausgegebene SVG angewendet wird. Sobald Sass zu CSS kompiliert ist, erhalten wir also eine schöne Dreh-Animation.

Ich arbeite immer noch daran

Mein Lieblingsteil des Generators ist die benutzerdefinierte Formenoption, bei der Sie Text, Emojis oder jedes SVG-Element hinzufügen können

The same circle spinner but using custom SVG shapes: one a word, one a poop emoji, and bright pink and orange asterisk.
Benutzerdefinierter Text, Emoji und SVG

Was ich tun möchte, ist, eine dritte Option für Stile hinzuzufügen, um nur ein Element zu haben, mit dem Sie mit Ihrem eigenen SVG-Element arbeiten können. So gibt es weniger zu bearbeiten und gleichzeitig einfachere Ausgaben zu ermöglichen.

Die Herausforderung bei diesem Projekt besteht darin, mit benutzerdefinierten Werten für so viele Dinge zu arbeiten, wie Dauer, Richtung, Entfernung und Winkel. Eine weitere Herausforderung für mich persönlich ist es, mich besser mit Vue vertraut zu machen, da ich zurückgehen und diesen unordentlichen Code bereinigen möchte. Das gesagt, das Projekt ist Open Source und Pull-Requests sind willkommen! Fühlen Sie sich frei, Vorschläge, Feedback oder sogar Vue-Kurs-Empfehlungen zu senden, insbesondere solche, die sich auf SVG oder die Erstellung von Generatoren beziehen.

Das alles begann mit einer Sass-Schleife, die ich in einem Buch gelesen habe. Es ist nicht der sauberste Code der Welt, aber ich bin von der Leistungsfähigkeit von SMIL-Animationen überwältigt. Ich empfehle wärmstens Sarah Soueidans Leitfaden für einen tieferen Einblick in das, was SMIL leisten kann.

Wenn Sie neugierig auf die Sicherheit von SMIL sind, das ist aus gutem Grund. Es gab eine Zeit, in der Chrome SMIL komplett einstellen wollte (siehe die einleitende Notiz in MDN). Aber diese Einstellung wurde ausgesetzt und (scheinbar) seitdem nicht mehr diskutiert.

Kann ich SMIL verwenden?

Diese Browser-Supportdaten stammen von Caniuse, das weitere Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.

Desktop

ChromeFirefoxIEEdgeSafari
54Nein796

Mobil / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
12712736.0-6.1