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

Animationen im Web wurden früher mit JavaScript erstellt. Mit der zunehmenden Nutzung von Mobilgeräten wurden Animationen jedoch auf CSS umgestellt, da es eine deklarative Syntax hat und Browser damit optimiert werden konnten. Da 60 fps auf Mobilgeräten immer das Ziel sind, sollten Sie sich nie außerhalb der Grenzen bewegen, die Browser effizient darstellen können.

Es gibt immer mehr Tools, mit denen sich JavaScript-gestützte Animationen effizienter gestalten lassen. Das Nonplusultra ist jedoch eine Kombination aus deklarativen und imperativen Animationen, bei der die Entscheidung, wie die Animationen geschrieben werden, davon abhängt, welcher Code am klarsten ist, nicht was in der einen Form und nicht in der anderen möglich ist.

Web-Animationen könnten diese Anforderung erfüllen. Der erste Teil davon wurde in Chrome 36 in Form von element.animate() eingeführt. Mit dieser neuen Funktion können Sie eine Animation vollständig in JavaScript erstellen und so effizient ausführen wie jede CSS-Animation oder ‑Übergang. Tatsächlich wird seit Chrome 34 genau dieselbe Web Animations-Engine für alle diese Methoden verwendet.

Die Syntax ist einfach und die einzelnen Teile sollten Ihnen bekannt sein, wenn Sie schon einmal eine CSS-Übergang oder -Animation geschrieben haben:

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

Der größte Vorteil dieser neuen Funktion ist, dass wir nicht mehr so viele komplizierte Schritte ausführen müssen, um eine flüssige, ruckelfreie Animation zu erhalten.

Für den Santa Tracker letzten Jahres wollten wir beispielsweise, dass es kontinuierlich schneit. Wir haben uns entschieden, die Animation über CSS auszuführen, damit sie effizient erfolgen konnte.

Wir wollten die horizontale Position des Schnees jedoch dynamisch anhand des Bildschirms und der Ereignisse in der Szene selbst auswählen. Die Höhe des Schneefalls (die Höhe des Browserfensters des Nutzers) war natürlich erst bekannt, wenn die Animation tatsächlich lief. Das bedeutete, dass wir CSS-Übergänge verwenden mussten, da das Erstellen einer CSS-Animation zur Laufzeit schnell komplex wird (und Hunderte von Schneeflocken Hunderte von neuen Stilregeln bedeuten).

Wir haben daher den folgenden Ansatz gewählt, der Ihnen bereits 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)';

Der Schlüssel ist der Kommentar „Einen Frame warten“. Damit ein Übergang gestartet werden kann, muss der Browser erkennen, dass sich das Element in der Startposition befindet. Dafür gibt es mehrere Möglichkeiten. Eine der häufigsten Methoden besteht darin, aus einer der Elementeigenschaften zu lesen, die den Browser zum Berechnen des Layouts zwingt. So wird sichergestellt, dass er weiß, dass das Element eine Startposition hat, bevor es zur Endposition übergeht. Mit dieser Methode können Sie sich auf Ihr überlegenes Wissen über die Browser-Interna beglückwünschen, während Sie sich bei jedem Tastenanschlag schmutzig fühlen.

Im Gegensatz dazu ist der entsprechende element.animate()-Aufruf sehr klar und gibt genau an, 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 ihre CSS-Entsprechungen können Web-Animationen 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 immer wichtiger wird, je mehr der Web Animations-Spezifikation veröffentlicht wird. Sowohl JavaScript- als auch CSS-Animationen haben zugehörige AnimationPlayer, mit denen sie nahtlos auf nützliche und interessante Weise kombiniert werden können.

Derzeit 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();

Und zur Erleichterung aller, die in der Vergangenheit versucht haben, ein Animationssystem mit CSS-Animationen oder ‑Übergängen zu erstellen, lösen Web-Animationen 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!');
}

Jetzt ausprobieren

Diese Funktionen sind in Chrome 36 verfügbar und werden heute in die Betaversion übernommen. Wenn Sie es ausprobieren möchten, verwenden Sie die native Implementierung in Chrome 36. Es gibt jedoch eine Web Animations-Polyfill, die einen deutlich größeren Teil der vollständigen Web Animations-Spezifikation in alle modernen, Evergreen-Browser einbringt.

In einer Demo des Schneeeffekts können Sie sowohl die native Version von element.animate() als auch die Polyfill-Version ausprobieren.

Ihre Meinung zählt

Es ist aber nur eine Vorschau auf das, was noch kommt. Wir veröffentlichen sie vor allem, um schnell Feedback von Entwicklern zu erhalten. Wir sind uns noch nicht sicher, ob wir alle Anwendungsfälle abgedeckt oder alle Ecken und Kanten der aktuellen APIs für Animationen geglättet haben. Die einzige Möglichkeit, wie wir das herausfinden und wirklich richtig machen können, ist, dass Entwickler es ausprobieren und uns ihre Meinung dazu mitteilen.

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

Update, Oktober 2014: In Chrome 39 werden mehrere zusätzliche Methoden zur Steuerung der Wiedergabe unterstützt, z. B. play(), pause() und reverse(). Außerdem ist es möglich, über die Property currentTime zu einem bestimmten Punkt in der Zeitachse einer Animation zu springen. In dieser neuen Demo können Sie sich diese Funktion in Aktion ansehen.

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