Wiedergabesteuerung für Webanimationen in Chrome 39

Anfang des Jahres wurde in Chrome 36 die Methode „element.animate“ in die umfassendere Webanimations-Spezifikation integriert. Das ermöglicht effiziente, native Animationen, die unbedingt erforderlich sind. So haben Entwickler die Möglichkeit, ihre Animationen und Übergänge mit dem für sie am besten geeigneten Ansatz zu erstellen.

Zur Erinnerung finden Sie hier eine Animation einer Wolke über den Bildschirm. Wenn Sie fertig sind, erhalten Sie einen Callback:

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

Dies allein ist unglaublich einfach und sollte als Teil Ihrer Toolbox beim Erstellen von Animationen oder Übergängen unbedingt berücksichtigt werden. In Chrome 39 wurden dem AnimationPlayer-Objekt, das von element.animate zurückgegeben wird, jedoch Funktionen zur Wiedergabesteuerung hinzugefügt. Bisher konnten Sie nach dem Erstellen einer Animation nur cancel() aufrufen oder das Ende-Ereignis warten.

Diese Ergänzungen bei der Wiedergabe eröffnen neue Möglichkeiten für Webanimationen: Sie können Animationen in ein universelles Tool umwandeln, anstatt Übergänge festzulegen, z.B. „feste“ oder vordefinierte Animationen.

Wiedergabe pausieren, zurückspulen oder die Wiedergabegeschwindigkeit ändern

Beginnen wir mit dem Aktualisieren des Beispiels oben, um die Animation zu pausieren, wenn auf die Wolke geklickt wird:

cloud.addEventListener('mousedown', function() {
    player.pause();
});

Sie können auch das Attribut playbackRate ändern:

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

Sie können auch die Methode reverse() aufrufen. Dies entspricht normalerweise dem Umkehren des aktuellen playbackRate (Multiplikation mit -1). Es gibt jedoch einige Sonderfälle:

  • Wenn die durch die Methode reverse() verursachte Änderung dazu führen würde, dass die laufende Animation effektiv endet, wird auch der currentTime invertiert. Wird z. B. eine ganz neue Animation umgekehrt, wird die gesamte Animation rückwärts abgespielt.

  • Wenn der Player pausiert wird, beginnt die Animation.

Scrubbing für den Player

Bei einer AnimationPlayer kann jetzt die currentTime während der Ausführung einer Animation geändert werden. Normalerweise erhöht sich dieser Wert im Laufe der Zeit oder nimmt er ab, wenn playbackRate negativ ist. Dadurch kann die Position einer Animation extern gesteuert werden, z. B. durch eine Nutzerinteraktion. Dies wird allgemein als Scrubbing bezeichnet.

Wenn beispielsweise auf Ihrer HTML-Seite der Himmel dargestellt wurde und Sie eine Ziehbewegung verwenden möchten, um die Position einer aktuell wiedergegebenen Wolke zu ändern, können Sie dem Dokument einige Handler hinzufügen:

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

Wenn Sie den Mauszeiger über das Dokument ziehen, wird die currentTime so geändert, dass die Entfernung zum ursprünglichen Termin widergespiegelt wird. Sie können die Wiedergabe der Animation auch fortsetzen, wenn die Touch-Geste beendet ist:

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

Dies könnte sogar mit einer Umkehrfunktion kombiniert werden, je nachdem, an welcher Stelle die Maus von der Seite gehoben wurde (kombinierte Demo).

Anstatt ein AnimationPlayer als Reaktion auf eine Nutzerinteraktion zu streichen, könnte sein currentTime auch verwendet werden, um den Fortschritt oder Status anzuzeigen, z. B. um den Status eines Downloads anzuzeigen.

Der Nutzen hierbei ist, dass ein AnimationPlayer die Festlegung eines Werts ermöglicht und dass die zugrunde liegende native Implementierung sich um die Visualisierung des Fortschritts kümmert. Im Download-Fall könnte die Dauer einer Animation auf die Gesamtgröße des Downloads und currentTime auf die aktuell heruntergeladene Größe (Demo) festgelegt werden.

UI-Übergänge und Touch-Gesten

Schon seit Langem werden mobile Plattformen häufig durch Gesten eingesetzt: Ziehen, Schieben, Ziehen und Ähnliches. Diese Gesten haben in der Regel ein gemeinsames Thema: eine verschiebbare UI-Komponente wie z. B. das Ziehen zum Aktualisieren in einer Listenansicht oder das Erstellen einer Seitenleiste von der linken Seite des Bildschirms.

Mit Web Animation lässt sich ein ähnlicher Effekt ganz einfach im Web nachbilden – auf dem Computer oder auf dem Mobilgerät. Wenn beispielsweise eine Geste zur Steuerung von currentTime ausgeführt wird:

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

Dadurch wird eine zusätzliche Animation erstellt, die ein „Drift“ ausführt. Dies wird zwischen dem Punkt, an dem die Geste ausgeführt wurde, bis zu unserem als funktionierend bekannten Ziel wiedergegeben.

Das funktioniert, da Animationen je nach Erstellungsreihenfolge Priorität haben: In diesem Fall hat driftPlayer Vorrang vor dem Player. Wenn driftPlayer abgeschlossen ist, verschwinden die Karte und die zugehörigen Effekte. Die letzte Zeit entspricht jedoch der aktuellen Uhrzeit des zugrunde liegenden Spielers. Die Benutzeroberfläche bleibt also einheitlich.

Wenn du Kätzchen magst, gibt es auch eine Demo-Webanwendung, in der diese Gesten zu sehen sind. Sie ist für Mobilgeräte optimiert und nutzt Polyfill für Abwärtskompatibilität. Versuche es also doch mal auf deinem Mobilgerät!

Gehen Sie weiter und „element.animate“

Die Methode element.animate ist jetzt absolut rockt – egal, ob du sie für einfache Animationen oder die zurückgegebene AnimationPlayer auf andere Weise verwendest.

Diese beiden Funktionen werden auch in anderen modernen Browsern über ein schlankes Polyfill vollständig unterstützt. Dieser Polyfill führt auch eine Funktionserkennung durch, sodass diese Funktion im Laufe der Zeit immer schneller und besser wird, wenn Browseranbieter die Spezifikation implementieren.

Die Web Animations-Spezifikation wird ebenfalls weiterentwickelt. Wenn du neue Funktionen ausprobieren möchtest, findest du sie jetzt auch in einem detaillierteren Polyfill: web-animations-next.