Tipps für effizienten Animationscode

Avatar of Zach Saucier
Zach Saucier am

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

Ich programmiere seit Jahren Webanimationen und helfe anderen dabei. Allerdings habe ich bisher keine prägnante Liste von Tipps gesehen, die sich darauf konzentrieren, wie man Animationen *effizient* erstellt. Hier sind sie!

Ich werde die GreenSock Animation Platform (GSAP) verwenden. Sie bietet eine einfache, lesbare API und löst Browser-Inkonsistenzen, sodass Sie sich auf Animationen konzentrieren können. Der Code und die Konzepte sollten auch dann verständlich sein, wenn Sie GSAP noch nie verwendet haben. Wenn Sie sich zuerst mit den Grundlagen von GSAP vertraut machen möchten, um das Beste aus diesem Artikel herauszuholen, ist die GSAP Getting Started-Seite (beinhaltet ein Video) der beste Ausgangspunkt.

Tipp #1: Verwenden Sie eine Animationsbibliothek

Einige Entwickler halten die Verwendung einer Animationsbibliothek für verschwendet, da sie native Browser-Technologien wie CSS-Übergänge, CSS-Animationen oder die Web Animations API (WAAPI) verwenden können, um dasselbe zu erreichen, ohne eine Bibliothek laden zu müssen. In einigen Fällen stimmt das. Hier sind jedoch einige weitere Faktoren zu berücksichtigen:

  • Browserfehler, Inkonsistenzen und Kompatibilität: Eine Animationsbibliothek wie GSAP löst diese Probleme für Sie und ist universell kompatibel. Sie können Bewegungspfade sogar in IE9 verwenden! Es gibt viele problematische Bereiche, wenn es um browserübergreifende Probleme geht, einschließlich der Handhabung von transform-origin auf SVG-Elementen, Pfadstrichen, 3D-Ursprüngen in Safari und vielen anderen, die wir hier nicht auflisten können.
  • Animations-Workflow: Das Erstellen auch nur moderat komplexer Animationen ist mit einem Tool wie GSAP viel schneller und unterhaltsamer. Sie können Animationen modularisieren, beliebig tief verschachteln und ihre Zeitsteuerung automatisch anpassen. Das macht das Experimentieren so viel einfacher. Glauben Sie mir: Sobald Sie versucht haben, eine Animationssequenz in CSS und dann in GSAP zu erstellen, werden Sie verstehen, was ich meine. Tag und Nacht! Zukünftige Bearbeitungen sind ebenfalls schneller.
  • Animieren über den DOM hinaus: Canvas, WebGL, generische Objekte und komplexe Strings können nicht mit nativen Technologien animiert werden. Die Verwendung eines einzigen konsistenten Tools für alle Ihre Animationen ist *wesentlich* sauberer.
  • Laufzeitsteuerung: Mit einer guten Animationsbibliothek können Sie eine gesamte Animationssequenz pausieren, fortsetzen, umkehren, durchsuchen oder sogar die Geschwindigkeit allmählich ändern. Sie können jede Transform-Komponente unabhängig steuern (Rotation, Skalierung, x, y, Schrägstellung usw.). Sie können diese Werte auch jederzeit abrufen. JavaScript-Animationen bieten Ihnen ultimative Flexibilität.
  • Easing-Optionen (Bounce, Elastic usw.): CSS bietet nur zwei Kontrollpunkte für Easing-Funktionen. GSAP's CustomEase ermöglicht es Ihnen, buchstäblich jedes beliebige Easing zu erstellen.
  • Lag-Glättung: GSAP kann die absolute Zeitsteuerung priorisieren oder Dinge im laufenden Betrieb anpassen, um Sprünge zu vermeiden, wenn die CPU überlastet ist.
  • Erweiterte Funktionen: Mit GSAP können Sie ganz einfach SVGs morphifizieren, Physik/Trägheit hinzufügen, Bewegungspfade direkt im Browser bearbeiten, positionsabhängige Staggering verwenden und mehr.

Die meisten Top-Animatoren der Branche verwenden ein Tool wie GSAP, weil sie diese Dinge im Laufe der Jahre gelernt haben. Sobald Sie über sehr einfache Animationen hinausgehen, wird eine JavaScript-Bibliothek Ihr Leben viel, viel einfacher machen und völlig neue Möglichkeiten eröffnen.

Tipp #2: Verwenden Sie Timelines

Eine gute Animationsbibliothek bietet eine Möglichkeit, einzelne Animationen (sogenannte Tweens) zu erstellen, und eine Möglichkeit, Animationen in einer Timeline zu sequenzieren. Stellen Sie sich eine Timeline wie einen Container für Ihre Tweens vor, in dem Sie sie relativ zueinander positionieren.

Wann immer Sie möchten, dass Ihre Animationen nacheinander ausgeführt werden, sollten Sie eine Timeline verwenden.

const tl = gsap.timeline(); 
tl.to(".box", { duration: 1, x: 100 })
  .to(".box", { duration: 1, backgroundColor: "#f38630" }, "+=0.5") 
  .to(".box", { duration: 1, x: 0, rotation: -360 }, "+=0.5")

Standardmäßig in GSAP warten die einer Timeline hinzugefügten Tweens darauf, dass die vorherigen Tweens abgeschlossen sind, bevor sie ausgeführt werden. Die Angabe +=0.5 fügt einen zusätzlichen Offset oder eine Verzögerung von einer halben Sekunde hinzu, sodass der zweite Tween 0,5 Sekunden nach Abschluss des ersten Tweens beginnt, unabhängig davon, wie lange die Dauer des ersten Tweens ist.

Um den Zeitabstand zwischen den Tweens auf 1 Sekunde zu erhöhen, müssen Sie nur +=0.5 in +=1 ändern! Super einfach. Mit diesem Ansatz können Sie Ihre Animationen schnell iterieren, ohne sich Gedanken über die Berechnung der Summe der vorherigen Dauern machen zu müssen.

Tipp #3: Verwenden Sie relative Werte

Unter "relativen Werten" verstehe ich drei Dinge:

  1. Animieren Sie Werte relativ zu ihrem aktuellen Wert. GSAP erkennt dafür die Präfixe += und -=. Also wird x: "+=200" 200 Einheiten (normalerweise Pixel) zum aktuellen x hinzufügen. Und x: "-=200" subtrahiert 200 vom aktuellen Wert. Dies ist auch im Positionsparameter von GSAP nützlich, wenn Tweens relativ zueinander positioniert werden.
  2. Verwenden Sie relative Einheiten (wie vw, vh und in einigen Fällen %), wenn Werte auf Änderungen der Bildschirmgröße reagieren müssen.
  3. Verwenden Sie Methoden wie .to() und .from() (anstelle von .fromTo()), wann immer möglich, damit die Start- oder Endwerte dynamisch aus ihren aktuellen Werten übernommen werden. So müssen Sie die Start- und Endwerte nicht in jedem Tween angeben. Juhu, weniger Tippen! Wenn Sie beispielsweise viele unterschiedlich gefärbte Elemente hätten, könnten Sie sie alle nach schwarz animieren mit gsap.to(".class", {backgroundColor: "black" }).

Tipp #4: Verwenden Sie Keyframes

Wenn Sie feststellen, dass Sie dasselbe Ziel immer wieder hintereinander animieren, ist das der perfekte Zeitpunkt, Keyframes zu verwenden! So geht's:

gsap.to(".box", { keyframes: [
  { duration: 1, x: 100 },
  { duration: 1, backgroundColor: "#f38630", delay: 0.5 }, 
  { duration: 1, x: 0, rotation: -360, delay: 0.5 }
]});

Keine Timeline erforderlich! Um die Tweens zu verteilen, verwenden wir einfach die delay-Eigenschaft in jedem Keyframe. (Sie kann negativ sein, um Überlappungen zu erzeugen.)

Tipp #5: Verwenden Sie intelligente Standardwerte

GSAP hat Standardwerte für Eigenschaften wie Easing ("power1.out") und Dauer (0.5 Sekunden). Der folgende Tween ist also gültig und wird eine halbe Sekunde dauern.

gsap.to(".box", { color: "black" })

Um die globalen Standardwerte von GSAP zu ändern, verwenden Sie gsap.defaults().

// Use a linear ease and a duration of 1 instead
gsap.defaults({ ease: "none", duration: 1 });

Dies kann praktisch sein, aber es ist üblicher, Standardwerte für eine bestimmte Timeline festzulegen, damit diese nur ihre Kinder beeinflusst. Wir können beispielsweise vermeiden, für jeden Unter-Tween duration: 1 einzugeben, indem wir einen Standardwert auf der übergeordneten Timeline festlegen.

const tl = gsap.timeline({ defaults: { duration: 1 } }); 
tl.to(".box", { x: 100 })
  .to(".box", { backgroundColor: "#f38630" }, "+=0.5") 
  .to(".box", { x: 0, rotation: -360 }, "+=0.5")

Tipp #6: Animieren Sie mehrere Elemente gleichzeitig

Das haben wir im dritten Tipp kurz erwähnt, aber es verdient einen eigenen Tipp.

Wenn Sie mehrere Elemente haben, die dieselbe Klasse .box teilen, animiert der obige Code alle Elemente gleichzeitig!

Sie können auch mehrere Elemente mit unterschiedlichen Selektoren auswählen, indem Sie eine komplexere Selektorzeichenkette verwenden.

gsap.to(".box, .circle", { ... });

Oder Sie können ein Array von Referenzen auf Variablen übergeben, solange die Elemente vom selben Typ sind (Selektorzeichenkette, Referenz auf eine Variable, generisches Objekt usw.).

var box = document.querySelector(".box");
var circle = document.querySelector(".circle");

// some time later…
gsap.to([box, circle], { ... });

Tipp #7: Verwenden Sie funktionsbasierte Werte, Stagger und/oder Schleifen

Funktionsbasierte Werte

Verwenden Sie eine Funktion anstelle einer Zahl/Zeichenkette für fast jede Eigenschaft, und GSAP ruft diese Funktion einmal für *jeden* Zielwert auf, wenn der Tween zum ersten Mal gerendert wird. Außerdem wird der von der Funktion zurückgegebene Wert als Eigenschaftswert verwendet! Das kann sehr nützlich sein, um eine Menge verschiedener Animationen mit einem einzigen Tween zu erstellen und Varianz hinzuzufügen.

GSAP übergibt die folgenden Parameter an die Funktion:

  1. Der Index
  2. Das spezifische Element, das betroffen ist
  3. Ein Array aller Elemente, die vom Tween betroffen sind

Zum Beispiel könnten Sie die Bewegungsrichtung basierend auf dem Index festlegen.

Oder Sie könnten Elemente aus einem Array auswählen.

Staggering

Machen Sie Ihre Animationen dynamischer und interessanter, indem Sie die Startzeiten mit einem Stagger versetzen. Für einfache gestaffelte Offsets in einem einzelnen Tween verwenden Sie einfach stagger: 0.2, um 0,2 Sekunden zwischen dem Start jedes Animationsbeginns hinzuzufügen.

Sie können auch ein *Objekt* übergeben, um komplexere Staggering-Effekte zu erzielen, einschließlich solcher, die sich vom Zentrum eines Rasters ausbreiten oder die Zeitplanung zufällig gestalten.

Weitere Informationen zu den Staggern von GSAP finden Sie in der Stagger-Dokumentation.

Schleifen

Es kann hilfreich sein, durch eine Liste von Elementen zu iterieren, um Animationen zu erstellen oder anzuwenden, insbesondere wenn sie auf einem Ereignis basieren, wie z. B. einer Benutzerinteraktion (darauf gehe ich später noch ein).

Um durch eine Liste von Elementen zu iterieren, ist es am einfachsten, .forEach() zu verwenden. Da dies jedoch in IE für mit .querySelectorAll() ausgewählte Elemente nicht unterstützt wird, können Sie stattdessen die Funktion utils.toArray() von GSAP verwenden.

Im folgenden Beispiel iterieren wir durch jeden Container, um seinen Kindern Animationen hinzuzufügen, die auf diesen Container beschränkt sind.

Tipp #8: Modularisieren Sie Ihre Animationen

Modularisierung ist eines der Schlüsselprinzipien der Programmierung. Es ermöglicht Ihnen, kleine, leicht verständliche Blöcke zu erstellen, die Sie zu größeren Kreationen kombinieren können, während Sie die Dinge sauber, wiederverwendbar und leicht zu modifizieren halten. Es ermöglicht Ihnen auch, Parameter und Funktions-Scopes zu verwenden, was die Wiederverwendbarkeit Ihres Codes erhöht.

Funktionen

Verwenden Sie Funktionen, um Tweens oder Timelines zurückzugeben und diese dann in eine Master-Timeline einzufügen.

function doAnimation() {
  // do something, like calculations, maybe using arguments passed into the function
  
  // return a tween, maybe using the calculations above
  return gsap.to(".myElem", { duration: 1, color: "red"});
}

tl.add( doAnimation() );

Das Verschachteln von Timelines kann die Art und Weise, wie Sie animieren, revolutionieren. Es ermöglicht Ihnen, *wirklich* komplexe Animationen einfach zu sequenzieren und Ihren Code modular und lesbar zu halten.

function doAnimation() {
  const tl = gsap.timeline();
  tl.to(...);
  tl.to(...);
  // ...as many animations as you’d like!

  // When you’re all done, return the timeline
  return tl;
}

const master = gsap.timeline();
master.add( doAnimation() );
master.add( doAnotherAnimation() );
// Add even more timelines!

Hier ist ein praktisches Beispiel, modifiziert aus Carl Schooffs Beitrag „Writing Smarter Animation Code“.

Hier ist eine komplexere Demo, die dieselbe Technik mit einem Star Wars-Thema von Craig Roblewsky zeigt.

Das Einkapseln Ihrer Animationserstellungsroutinen in Funktionen macht auch die Neuerstellung von Animationen (z. B. bei Größenänderung) zum Kinderspiel!

var tl; // keep an accessible reference to our timeline

function buildAnimation() {
  var time = tl ? tl.time() : 0; // save the old time if it exists

  // kill off the old timeline if it exists
  if (tl) {
    tl.kill();
  }

  // create a new timeline
  tl = gsap.timeline();
  tl.to(...)
    .to(...); // do your animation
  tl.time(time); // set the playhead to match where it was
}

buildAnimation(); //kick things off

window.addEventListener("resize", buildAnimation); // handle resize

Wenn Sie immer wieder denselben Code wiederholen und nur eine Variable durch eine andere ersetzen, ist das normalerweise ein Zeichen dafür, dass Sie eine allgemeine Funktion erstellen oder stattdessen eine Schleife verwenden sollten, um Ihren Code DRY (Don't Repeat Yourself) zu halten.

Effekte

Mit Effekten können Sie eine benutzerdefinierte Animation in einen benannten Effekt verwandeln, der jederzeit mit neuen Zielen und Konfigurationen aufgerufen werden kann. Dies ist besonders hilfreich, wenn Sie Standards für Ihre Animationen haben oder wenn Sie dieselbe Animation aus verschiedenen Kontexten aufrufen möchten.

Hier ist ein super einfacher "Fade"-Effekt, um das Konzept zu veranschaulichen.

// register the effect with GSAP:
gsap.registerEffect({
    name: "fade",
    defaults: {duration: 2}, //defaults get applied to the "config" object passed to the effect below
    effect: (targets, config) => {
        return gsap.to(targets, {duration: config.duration, opacity:0});
    }
});

// now we can use it like this:
gsap.effects.fade(".box");
// Or override the defaults:
gsap.effects.fade(".box", {duration: 1});

Tipp #9: Verwenden Sie Steuerungsmethoden

GSAP bietet viele Methoden zur Steuerung des Zustands eines Tweens oder einer Timeline. Dazu gehören .play(), .pause(), .reverse(), .progress(), .seek(), .restart(), .timeScale() und mehrere andere.

Die Verwendung von Steuerungsmethoden kann Übergänge zwischen Animationen flüssiger gestalten (z. B. die Möglichkeit, mitten in einer Animation umzukehren) und performanter machen (durch Wiederverwendung desselben Tweens/derselben Timeline anstatt bei jedem Mal neue Instanzen zu erstellen). Und durch feinere Kontrolle über den Animationszustand kann dies auch beim Debugging helfen.

Hier ist ein einfaches Beispiel

Ein erstaunlicher Anwendungsfall ist das Tweening der timeScale einer Timeline!

Anwendungsfall: Interaktionsereignisse, die Animationen auslösen

Innerhalb von Ereignis-Listenern für Benutzerinteraktionsereignisse können wir Steuerungsmethoden verwenden, um die Wiedergabezustände unserer Animationen fein zu steuern.

Im folgenden Beispiel erstellen wir für jedes Element eine Timeline (damit nicht dieselbe Animation für alle Instanzen ausgelöst wird), speichern eine Referenz dieser Timeline am Element selbst und spielen dann die relevante Timeline ab, wenn das Element überfahren wird, und kehren sie um, wenn die Maus den Bereich verlässt.

Anwendungsfall: Animieren zwischen mehreren Zuständen einer Timeline

Sie möchten möglicherweise, dass eine Reihe von Animationen dieselben Eigenschaften derselben Elemente beeinflusst, aber nur in bestimmten Sequenzen (z. B. aktive/inaktive Zustände, jeweils mit Maus-Over-/Maus-Out-Zuständen). Das kann schwierig zu verwalten sein. Wir können es vereinfachen, indem wir Zustände einer Timeline und Steuerelemente verwenden.

Anwendungsfall: Animieren basierend auf der Scroll-Position

Wir können Animationen einfach basierend auf der Scroll-Position auslösen, indem wir Steuerungsmethoden verwenden. Dieses Demo spielt zum Beispiel eine vollständige Animation ab, sobald eine bestimmte Scroll-Position erreicht ist.

Sie können den Fortschritt einer Animation auch an die Scroll-Position koppeln, um ausgefallenere Scroll-Effekte zu erzielen!

Wenn Sie dies jedoch tun, ist es aus Performance-Gründen am besten, den Scroll-Listener zu drosseln.

Das jedes Mal einzurichten, wenn Sie eine Scroll-Animation durchführen müssen, ist jedoch mühsam. Sie können GreenSock's offizielles Scroll-Plugin namens ScrollTrigger verwenden, um dies (und vieles mehr) für Sie zu erledigen!

Bonus-Tipp: Verwenden Sie GSAPs Plugins, Utility-Methoden und Hilfsfunktionen

GSAP-Plugins erweitern die Kernfunktionalität von GSAP um zusätzliche Fähigkeiten. Einige Plugins erleichtern die Arbeit mit Rendering-Bibliotheken wie PixiJS oder EaselJS, während andere Plugins Superkräfte wie SVG-Morphing, Drag-and-Drop-Funktionalität usw. hinzufügen. Dies hält den GSAP-Kern relativ klein und ermöglicht es Ihnen, Funktionen hinzuzufügen, wenn Sie sie benötigen.

Plugins

ScrollTrigger erstellt atemberaubende Scroll-basierte Animationen mit minimalem Code. Oder lösen Sie alles Scroll-bezogene aus, auch wenn es nichts mit Animation zu tun hat.

MorphSVG morpht zwischen zwei beliebigen SVG-Formen, unabhängig von der Punktanzahl, und gibt Ihnen feine Kontrolle darüber, wie die Formen morph werden.

DrawSVG enthüllt (oder verbirgt) den Strich eines SVG-Elements schrittweise und lässt es so aussehen, als würde es gezeichnet. Es umgeht verschiedene Browserfehler, die typische stroke-dashoffset-Animationen beeinträchtigen.

MotionPath animiert *alles* (SVG, DOM, Canvas, generische Objekte, was auch immer) entlang eines Bewegungspfades in *jedem* Browser. Sie können den Pfad sogar im Browser mit MotionPathHelper bearbeiten!

GSDevTools bietet eine visuelle Benutzeroberfläche zum Interagieren mit und Debuggen von GSAP-Animationen, komplett mit erweiterten Wiedergabesteuerungen, Tastenkombinationen, globaler Synchronisation und mehr.

Draggable bietet eine überraschend einfache Möglichkeit, praktisch jedes DOM-Element mit Maus- oder Touch-Events ziehbar, drehbar, werfbar oder sogar durchwischbar zu machen. Draggable lässt sich hervorragend (und optional) mit InertiaPlugin integrieren, sodass der Benutzer eine Bewegung auslösen und die Bewegung basierend auf dem Schwung sanft abbremsen kann.

CustomEase (zusammen mit CustomBounce und CustomWiggle) erweitern die bereits umfangreichen Easing-Fähigkeiten von GSAP, indem sie es Ihnen ermöglichen, *jedes* gewünschte Easing zu registrieren.

SplitText ist ein einfach zu bedienendes JavaScript-Dienstprogramm, mit dem Sie HTML-Text in Zeichen, Wörter und Zeilen aufteilen können. Es ist einfach zu bedienen, äußerst flexibel, funktioniert bis zurück zu IE9 und kümmert sich um Sonderzeichen für Sie.

ScrambleText vermischt den Text in einem DOM-Element mit zufälligen Zeichen, aktualisiert in regelmäßigen Abständen neue zufällige Zeichen und enthüllt schrittweise Ihren neuen Text (oder den ursprünglichen) während der Dauer des Tweens. Visuell sieht es aus wie ein Computer, der eine Textzeichenfolge dekodiert.

Physics2D ermöglicht es Ihnen, die Position von Elementen basierend auf Geschwindigkeit und Beschleunigung zu tweeen, anstatt zu bestimmten Werten zu gehen. PhysicsProps ist ähnlich, funktioniert aber mit jeder Eigenschaft, nicht nur mit 2D-Koordinaten.

Utility-Methoden

GSAP verfügt über integrierte Utility-Methoden, die einige gängige Aufgaben erleichtern können. Die meisten konzentrieren sich auf die Manipulation von Werten auf eine bestimmte Weise, was besonders hilfreich sein kann, wenn Animationswerte generiert oder modifiziert werden. Die, die ich am häufigsten verwende, sind .wrap(), .random, .interpolate(), .distribute(), .pipe() und .unitize(), aber es gibt noch viele andere, die Sie nützlich finden könnten.

Hilfsfunktionen

In einem ähnlichen Sinne, aber nicht in den Kern von GSAP integriert, gibt es einige Hilfsfunktionen, die GreenSock im Laufe der Jahre zur Bewältigung spezifischer Anwendungsfälle entwickelt hat. Diese Funktionen erleichtern das FLIP Ihrer Animationen, geben eine Zufallszahl basierend auf einer Ease-Kurve zurück, mischen zwei Ease-Kurven und vieles mehr. Ich empfehle Ihnen dringend, diese auszuprobieren!

Fazit

Sie haben es bis zum Ende geschafft! Hoffentlich haben Sie ein oder zwei Dinge gelernt und dieser Artikel wird Ihnen auch in den kommenden Jahren eine Ressource sein.

Wie immer, wenn Sie Fragen zu GSAP haben, können Sie sich gerne an die GreenSock-Foren wenden. Sie sind unglaublich hilfreich und einladend! Als Mitarbeiter von GreenSock halte ich mich dort oft auf; ich helfe gerne Leuten beiAnimations-Herausforderungen!