Grenzen der CSS-Keyframes-Animationen
CSS führt Animationen für eine vorgegebene Dauer aus, mit einem Zähler der Iterationen (Durchläufe) und evtl. mit einer Verzögerung vor dem Start. Ohne Weiteres starten CSS-Animationen mit dem Laden der Seite, aber meist triggert Javascript CSS-Animationen durch Hinzufügen oder Entfernen von CSS-Klassen.
Einfache CSS-Keyframes-Animation aus dem CSS-Menü
CSS-Animationen wirken nur auf individuelle Elemente. CSS erkennt keine Abhängigkeiten zwischen dem Verhalten der einzelnen Elemente. CSS kann nicht feststellen, ob eine Animation noch läuft oder beendet ist, also gibt es auch keine Option, eine Animation anzustoßen, wenn eine andere Animation beendet ist. Dafür wird wieder Javascript benötigt.
Web Animation API: element.animate ()
An dieser Stelle springt das Web Animation API (Application Programming Interface) ein. Javascript animate () hat zwei Argumente: ein Array von Keyframes und ein Objekt mit den Optionen für die Steuerung des Ablaufs.
+-- Javascript Object mit Eigenschaften | wie Dauer, Iterationen, Verzögerung | animate (keyframes, options) | | +-- Array von Keyframes
const wheel = document.querySelector (".wheel").animate ( [ { transform: "rotate(0deg)" }, { transform: "rotate(360deg)" } ], { duration: 2000, iterations: Infinity } );
Javascript animate() vs CSS-Keyframes-Animationen
An einigen Stellen müssen wir uns beim Umschalten von Keyframes-Animationen auf Javascript animate an kleine Unterschiede gewöhnen.
Dauer der Animation
CSS: Sekunden
Javascript: Millisekunden
Eigenschaften
CSS: mit Bindestrichen
Javascript: CamelCase
Easing-Voreinstellung
CSS: ease-in
Javascript: linear
Iteration
CSS: infinite
Javascript: Infinity
- Während Zeitangaben in CSS in Bruchteilen von Sekunden geschrieben werden – 0.5s für eine halbe Sekunde – schreibt Javascript die Dauer in Millisekunden. Aus CSS 0.5s wird 500, eine Sekunde in Javascript ist einfach 1000, immer als reine Zahl ohne "s" für Sekunden.
- Javascript verweigert bei Bindestrichen. CSS-Eigenschaften wie background-color werden im CamelCase geschrieben, also ohne Bindestrich, der erste Buchstabe nach dem Bindestrich wird zur Versalie (Großbuchstabe). Aus CSS background-color wird backgroundColor, aus border-radius borderRadius. Es gibt keine Javascript-Methode, die eine automatisch Übersetzung leistet.
- Und noch ein Unterschied: CSS-Animationen laufen vorgabegemäß langsam an und werden dann schneller: ease-in. Javascript animate hingegen hat keine Vorgaben, sondern Javascript-Animationen laufen per se linear ab. Wenn Easing erwünscht ist, muss es entweder in den / die Keyframe(s) oder für die gesamte Animation in die Optionen.
Javascript animate()-Slideshow
Nehmen wir die einfache CSS-Slideshow oben von dieser Seite und übersetzen sie in eine Javascript animate ()-Slideshow. Das HTML-Markup ist dasselbe: einfach fünf img-Elemente in einem relativ positionierten div-Element.
Die Keyframes sind als Array keyframes angelegt. offset steht anstelle der 0%, 20%, 22%, 99% und 100% der CSS-Animation. Der Offset liegt zwischen 0 und 1. Die Option der Slideshow sitzen als Objekt in der animate-Methode.
Die Gesamtdauer der Animation beträgt 40 Sekunden, also 8 Sekunden für jedes der fünf Bilder. Die Konstante time macht die Animation flexibler.
const time = 8000; const keyframes = [ { opacity: 1, offset: 0, transform: "translateX(0)" }, { opacity: 1, offset: 0.2, transform: "translateX(0)"}, // 1/5 der Dauer sichtbar { opacity: 0, offset: 0.24, transform: "translateX(100%)"}, // ein Moment für transformX { opacity: 0, offset: 0.99, transform: "translateX(0)" }, // 4/5 der Dauer nicht sichtbar { opacity: 1, offset: 1, transform: "translateX(0)" } ]; for (const [index, item] of slides.entries ()) { item.animate ( keyframes, { duration: 5 * time, delay: 5 * time - (index + 1) * time, fill: "forwards", easing: "ease-out", iterations: Infinity } ); }
Play- und Pause-Button sind eine einfache Ergänzung der Slideshow.
const slidesElem = document.querySelector (".slidesJS"); const player = document.createElement ("div"); player.setAttribute ("style", "width:100%;font-size:3rem;color:white;…"); player.textContent = "⏵︎"; slidesElem.append (player);
Nur noch ein eventListener für den Klick auf den Play-Button und eine Funktion zum Pausieren der Animation: getAnimations() nimmt sich alle Animationen des Dokuments und wirkt auch auf die reine CSS-Slideshow oben und die simple CSS-Uhr (die so schön praktisch fürs Testen der Animation ist).
function stopAnimation () { document.getAnimations().map((elem) => { if (elem.playState === "running") { elem.pause (); player.textContent = "II"; } else if (elem.playState === "paused") { elem.play (); player.textContent = "⏵︎"; } }); } document.querySelector (".slidesJS").addEventListener ("click", stopAnimation);
Javascript Animationen steuern
Die meisten einfachen Animationen lassen sich ebenso gut mit CSS wie mit Javascript steuern. Die Animation von komplexen Objekten und Abläufen wird hingegen besser bei Javascript aufgehoben sein.
Der Vorsprung von Javascript gegenüber CSS-Animationen beruht in der Vielzahl von Events, die eine Animation starten, pausieren und beenden.
<div class="cardo"> <wheel-animation></wheel-animation> </div> <button onclick="wheel.play()">PLAY</button> <button onclick="wheel.pause()">PAUSE</button> <button onclick="wheel.playbackRate += 0.2">schneller</button> <button onclick="wheel.playbackRate -= 0.2">langsamer</button>
Javascript animate () listet im Keyframes-Array CSS-Eigenschaften auf, mehrere Eigenschaften werden durch Kommas voneinander getrennt.
let wheel = document.querySelector ("wheel-animation").animate ( [ { transform: "translateX(0) rotate(0deg)", easing: "ease-in"}, { transform: "translateX("+ width + "px) rotate(" + (umdrehungen * 360) + "deg)" }, { transform: "translateX(0) rotate(0deg)", easing: "ease-out"} ], { duration: duration, iterations: Infinity } );
Das Script berechnet die Laufstrecke und den Kreisumfang, um die Animation an die Laufstrecke anzupassen. Ein kleines Extra, das mit CSS nicht zu bewältigen wäre.
Ein weiterer Vorteil von Javascript animate() gegenüber CSS-Animationen: Die Javascript-Console meldet Typos und Fehler – die Fehlersuche in CSS hingegen ist oft mühselig.
Javascript Web Animation API vs requestAnimationFrame
Die klassische Javascript-Animation mit setInterval und requestAnimationFrame basiert auf Loops – auf Schleifen, in denen komplexe Animationen ausgeführt werden. Dabei kann Javascript neben dem animierten Element auch weitere Elemente beachten und auf ihr Verhalten reagieren.
Wir können z.B. die Werte eines Elements A nutzen, um ab einer bestimmten Position oder Größe die Animation von Element B zu starten oder anzuhalten. Die dafür erforderlichen Berechnungen und Interpolationen können allerdings bei Farbwerten oder dem Fortschritt eines clipPath kompliziert werden. Obendrein müssen auch Verhaltensweisen wie Beschleunigen und Abbremsen für jeden Frame berechnet werden, denn die klassischen Javascript-Animationen hatten keine easing-Funktionen.Für Canvas-Animationen hingegen bleibt requestAnimationFrame weiterhin unersetzlich, denn das Web Animation API wirkt nur auf Objekten.
API – Web Application Interface
- Fetch API
- Geolocation API
- Canvas API
- Web Storage API
- Intersection Observer API
- Web Workers API
- File API
- Clipboard API