„Web Animations“ – element.animate() – jetzt in Chrome 36

Brendan
Brendan Kenny

Animationen im Web waren früher eine Provinz von JavaScript, aber als die Welt auf Mobilgeräte umzog, wurden Animationen für die deklarative Syntax und die Optimierungen, die Browser damit vornehmen konnten, in CSS verschoben. Bei mobilen Anzeigen sind 60 fps immer dein Ziel. Daher ist es sinnvoll, den Browser zu verlassen, der eine effiziente Darstellung ermöglicht.

Es scheint, dass immer mehr Tools JavaScript-gesteuerte Animationen effizienter werden, aber der Heilige Gral ist eine Vereinigung von deklarativen und imperativen Animationen, bei denen die Entscheidung, wie Ihre Animationen geschrieben werden, davon abhängt, welcher Code eindeutig ist, nicht darauf, was in einer Form und nicht in der anderen möglich ist.

Web Animations steht für diesen Anruf. Der erste Teil davon ist in Chrome 36 gelandet, nämlich element.animate(). Mit dieser neuen Funktion können Sie Animationen ausschließlich in JavaScript erstellen und diese genauso effizient ausführen wie CSS-Animationen oder -Übergänge (ab Chrome 34 wird genau dieselbe Web Animations-Engine für alle diese Methoden verwendet).

Die Syntax ist einfach und die Bestandteile sollten Ihnen vertraut sein, wenn Sie schon einmal CSS-Übergänge oder -Animationen geschrieben haben:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

Der größte Vorteil dieser neuen Funktion ist der Wegfall vieler kniffliger Rätsel, die wir früher lösen mussten, um eine flüssige Animation ohne Ruckeln zu erhalten.

Im letzten Jahr wollten wir beispielsweise für Santa Tracker kontinuierlich Schnee fallen lassen und beschlossen, ihn über CSS zu animieren, damit er so effizient sein kann.

Wir wollten jedoch die horizontale Position des Schnees dynamisch basierend auf dem Bildschirm und den Ereignissen in der Szene auswählen. Natürlich war die Höhe des Schneesfalls (die Höhe des Browserfensters des Nutzers) erst bekannt, wenn wir tatsächlich ausgeführt wurden. Das bedeutete, dass wir wirklich CSS-Übergänge verwenden mussten, da das Erstellen einer CSS-Animation zur Laufzeit schnell komplex wird (und Hunderte von Schneeflocken bedeuten Hunderte von neuen Stilregeln).

Daher haben wir den folgenden Ansatz gewählt, der Ihnen bekannt sein sollte:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

Entscheidend ist dieser "wait a Frame"-Kommentar. Damit ein Übergang erfolgreich gestartet werden kann, muss der Browser bestätigen, dass sich das Element an der Startposition befindet. Dafür gibt es mehrere Möglichkeiten. Eine der gängigsten Methoden besteht darin, aus einer der Elementeigenschaften zu lesen, die den Browser zwingt, das Layout zu berechnen. Dadurch wird sichergestellt, dass das Element vor dem Übergang zur Endposition weiß, dass das Element eine Startposition hat. Mit dieser Methode können Sie sich selbst zu Ihren hervorragenden Kenntnissen über interne Browserfunktionen beglückwünschen, ohne sich mit jedem Tastenanschlag zu verunsichern.

Im Gegensatz dazu könnte der entsprechende element.animate()-Aufruf nicht deutlicher formuliert werden, da er genau aussagt, was beabsichtigt ist:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

Es gibt noch viele weitere Optionen. Genau wie CSS-Entsprechungen können auch Webanimationen verzögert und iteriert werden:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate() gibt tatsächlich ein AnimationPlayer-Objekt zurück, das mit zunehmender Bedeutung der Web Animations-Spezifikation immer wichtiger wird. Sowohl mit JavaScript als auch mit CSS erstellte Animationen sind mit AnimationPlayern verknüpft, sodass sie auf nützliche und interessante Weise nahtlos kombiniert werden können.

Vorerst bietet AnimationPlayer jedoch nur zwei Funktionen, die beide sehr nützlich sind. Sie können eine Animation jederzeit mit AnimationPlayer.cancel() abbrechen:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

Zur Erleichterung aller, die in der Vergangenheit versucht haben, ein Animationssystem mit CSS-Animationen oder -Übergängen zu erstellen, lösen Web Animations immer ein Ereignis aus, wenn sie fertig sind:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

Ausprobieren

All dies wird in Chrome 36 eingeführt und ist ab heute als Betaversion verfügbar. Wenn Sie sie ausprobieren möchten, arbeiten Sie mit der nativen Implementierung in Chrome 36. Es gibt jedoch einen Web Animations-Polyfill, der einen erheblich größeren Teil der vollständigen Web Animations-Spezifikation in alle modernen, zeitlosen Browser einbindet.

Es ist eine Demo des Schnee-Effekts verfügbar, mit der du sowohl die native Version von element.animate() als auch polyfill ausprobieren kannst.

Ihre Meinung zählt

Tatsächlich ist dies jedoch nur eine Vorschau auf die zukünftigen Funktionen und wird speziell veröffentlicht, um sofort Feedback von Entwicklern zu erhalten. Wir sind uns noch nicht sicher, ob wir jeden Anwendungsfall erreicht oder die Ränder der aktuellen APIs für Animationen abgerundet haben. Wir können das nur richtig verstehen, wenn Entwickler sie ausprobieren und uns ihre Meinung mitteilen.

Kommentare zu diesem Beitrag sind natürlich wertvoll. Kommentare zum Standard selbst können über die public-fx-Mailingliste an die CSS- und SVG-Arbeitsgruppen gerichtet werden.

Update, Oktober 2014: In Chrome 39 werden mehrere zusätzliche Methoden zur Steuerung der Wiedergabe unterstützt, darunter play(), pause() und reverse(). Außerdem ist es möglich, mit der Eigenschaft currentTime zu einem bestimmten Punkt auf der Zeitachse einer Animation zu springen. In dieser neuen Demo können Sie sich ein Bild davon machen.

Vielen Dank an Addy Osmani und Max Heinritz für ihre Hilfe bei diesem Beitrag.