Javascript Web Animation API

Javascript Animationen mit Web Animation Api

Mit elem.animate() stellt das Web Animation API ein flexibles Scripting für Animationen bereit und wird von allen modernen Browsern unterstützt: animate (keyframes, options). Wer bereits mit CSS-Keyframes-Animationen vertraut ist, erkennt die Gemeinsamkeiten: Der Aufruf von animate () setzt ein Array von Keyframes mit Dauer und der Zahl der Wiederholungen ein.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

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.

Fischerkahn, Rees am Rhein Slideshow Kahn Laterne auf der Terasse Obst,Gemüse und Obstschale Duisburg Ruhrort

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

  1. 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.
  2. 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.
  3. 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.

Fischerkahn, Rees am Rhein Slideshow Kahn Laterne auf der Terasse Obst,Gemüse und Obstschale Duisburg Ruhrort

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 }
	);
}

Der Play- und Pause-Button ist 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.