Web Animations/Animationen steuern

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Einer der Nachteile von CSS-Animation und Transition ist das Fehlen von Möglichkeiten zur Steuerung.

Dieses Tutorial zeigt, wie man mit der Web Animations API Animationen durch den Benutzer kontrollieren lassen kann. Diese API findet sich nativ in allen Browsern, externe Bibliotheken wie GSAP oder Anime.js werden nicht benötigt.

Dabei animieren wir nicht nur Gimmicks und Show-Effekte, sondern aussagekräftige Inhalte und die Aufmerksamkeit des Benutzers.

CSS-Animation

Das letzte Beispiel aus dem CSS-Animation-Tutorial zeigt einen Loading-Spinner, der bei :hover pausiert:

Animation mit CSS ansehen …
#gear {
    animation: run 3500ms linear infinite;
}

#gear:hover {
	animation-play-state: paused;
}

@keyframes run {
    0% {
        rotate: 0;
    }
    100% {
        rotate: 1turn;
    }
}

Die Eigenschaft animation-play-state wird beim Überfahren mit der Maus auf animation-play-state: paused; gesetzt. Die Animation pausiert, bis sich die Maus wieder entfernt.

Weitere Steuerungsmöglichkeiten wie eine Änderung der Richtung oder Geschwindigkeit sind nicht möglich.

Und das Gleiche mit JavaScript

Gerade, wenn Nutzer Einfluss nehmen, sind Tricks wie das Selektieren mit target ein Verstoß gegen die Trennung von Inhalt, Präsentation und Verhalten. Deshalb nehmen wir jetzt JavaScript zu Hilfe und bauen unseren Loading-Spinner nach:

Animation mit Web Animations ansehen …
const animation = gear.animate(
  [
    { rotate: "0" },
    { rotate: "1turn" }
  ],
  {
    duration: 3500,
    iterations: Infinity
  }
);

playBtn.addEventListener("click", () => {
  animation.play();
});

pauseBtn.addEventListener("click", () => {
  animation.pause();
});

In diesem Beispiel wird in einem script-Bereich eine Konstante animation definiert. Sie ruft für gear die Element.animate(keyframes, options)-Methode auf, die ein Animations-Objekt erzeugt.

Dies enthält zwei Parameter:

  1. keyframes entsprechen den @keyframes von CSS
    • Es enthält einen Array der CSS-Eigenschaft(en) – hier nur rotate und die zu verändernden Werte.
      (Alternativ wäre auch eine Objektschreibweise möglich, in der CSS-Eigenschaften einen Array der zu animierenden Werte enthalten.)
  2. In den options finden sich die

Wie in CSS-Animation startet eine Web Animation sofort beim Laden. Falls man das nicht will, muss ein animation.pause(); eingefügt werden.

Beachte: So ähnlich sich CSS-Animation und die WAAPI sind, gibt es einige Unterschiede:
  • In JS sind nur Zeitangaben im ms möglich, in CSS gegen sowohl ms als auch s.
  • In JS lautet das Schlüsswort für unendliche Wiederholungen Infinity – in CSS infinite
  • In JS verlaufen Animation standardmäßig linear, in CSS ist der Default für animation-timing-function ease-in.
  • CSS-Eigenschaften mit Bindestrich werden in JavaScript in CamelCase notiert.

Pausieren bei :hover?

Es gibt kein einfaches Abfragen des :hover-Selektors in JavaScript. Stattdessen können die Maus-Events überprüft werden:

Pausieren beim Überfahren mit der Maus
gear.addEventListener("mouseenter", () => animation.pause());
gear.addEventListener("mouseleave", () => animation.play());

Mit AddEventListener werden die mouseenter und mouseleave-Events belauscht. Feuern sie, wird die Animation pausiert oder wieder aufgenommen.

Cards mit WAAPI

Ein klassisches Problem bei CSS-Animationen ist ihre Einbahnstraße.
Sehr oft wünscht man sich: Die gleiche Animation soll vorwärts und rückwärts laufen können.

Mit reinem CSS führt das schnell zu doppeltem Code, mehreren @keyframes oder komplizierten Workarounds.

Ein typisches Beispiel ist eine Karte, die zu einer Detailansicht erweitert wird:

  • Erster Klick → die Karte klappt auf
  • Zweiter Klick → sie schließt sich wieder
    Idealerweise mit derselben Animation – nur rückwärts

Genau an diesem Punkt zeigt die Web Animations API ihre Stärke:
Animationen sind keine starren Deklarationen mehr, sondern steuerbare Objekte, deren Richtung jederzeit geändert werden kann.


Für ein Kräuterlexikon wollen wir Cards anlegen, bei denen der Nutzer auf Wunsch weitere Informationen erhalten kann:

Card - HTML-Markup
<div class="card">
	<header>
		<h2>Basilikum<span class="icon">🌱</span></h2>
	</header> 
  <p class="card-teaser"> Ein aromatisches Küchenkraut, perfekt für … </p> 
  <button class="toggle" aria-expanded="false">Mehr erfahren</button> 
  <section class="card-details" hidden> 
  	<h3>Pflegehinweise</h3></section> 
</div>

<p id="controls">
  <button id="playBtn">Los</button>
  <button id="pauseBtn">Pause</button>
  <button id="reverseBtn">Zurück</button>
  <!-- Nur zu Demo-Zwecken -->
</p>

Wir haben eine Karte mit header, teaser und einem button, der eine section mit Pfleghinweisen aufklappen kann. Sie ist anfänglich mit dem hidden-Attribut ausgeblendet.

Die Karte ist immer dieselbe – nur ihr Informationsgrad verändert sich.

Die Buttons sind eigentlich „unnatürlich“ für echte UIs, hier machen sie die Zeit sichtbar!


Card-details ein- und ausblenden ansehen …
details.hidden = false;

const detailsAnimation = details.animate(
  [
    { opacity: 0, translate: "0 1em" },
    { opacity: 1, translate: "0 0" }
  ],
  {
    duration: 300,
    easing: "ease",
    fill: "both",
    delay: 150
  }
);

detailsAnimation.pause();

Das hidden-Attribut wird nicht animiert, sondern nur auf false gesetzt. Stattdessen wird ein Animationsobjekt angelegt, dass im keyframe-Objekt die opacity auf 0 setzt und den Textinhalt mit translate um 1em verschiebt.

Sobald das Animations-Objekt mit detailsAnimation.play(); aufgerufen wird, werden die Werte für opacity und translate animiert und der Textinhalt erscheint.

Wir haben kein Klassen-Geschiebe von button und .card-details, keine doppelten keyframes, sondern bewegen uns auf demselben Zeitstrahl vor und zurück.

Die sorgt für eine bessere separation of concerns:

  • Layout       → CSS (width, aspect-ratio)
  • Bewegung → WAAPI
  • Zustände   → JS
Beachte, dass man für eine CSS-Werteliste für mehrere Werte Anführungszeichen für den String benötigt.
Sowohl die Keyframes als auch die Timing Options werden in Literal-Schreibweise notiert. Die einzelnen Werte werden durch Kommata getrennt; am Ende einer Aufzählung darf aber kein Komma mehr stehen.
Dieser Umstand sorgt immer wieder für Fehlerquellen und sollte deshalb von jedem Script-Autor jedes Mal peinlich genau überprüft werden.

Wenn man einfach nur Inhalte aufklappen will, eignet sich ein details-Element besser. In unserem Beispiel wollen wir aber denselben Übergang vorwärts und rückwärts abspielen, pausieren und jederzeit fortsetzen können.

Unterbrechung und Zustandsrobustheit

Bisher funktioniert die Karte hervorragend, wenn sich der Benutzer korrekt verhält:

Klicken > Warten > Erneut klicken

Echte Benutzer tun das jedoch nicht! Sobald jemand zweimal schnell hintereinander oder während der Animation klickt, beginnen CSS-Übergänge instabil zu werden. Genau hier glänzt WAAPI.


ToDo (weitere ToDos)

--Matthias Scharwies (Diskussion) 05:43, 6. Jan. 2026 (CET)




Fazit

Mit diesem Script haben wir einen Player, der eine Animation abspielen, auf Wunsch aber auch stoppen oder rückwärts laufen lassen kann. Im nächsten Kapitel wollen wir anstelle eines Karussells die Bilder nacheinander fließend einblenden.


Weblinks