Javascript Web Animation Api: onfinish, oncancel
Genauso wie bei einer CSS-Animation wird ein animiertes Element wie ein absolut positioniertes Element behandelt und hat keinen Einfluß auf vorangehende oder folgende Elemente. Die CSS-Stile, die von der Animation manipuliert wurden, tauchen anders als bei den klassischen Animationstechniken im DOM nicht auf.
const elem = document.querySelector("#circle"); let currentAnimation; function move (transformStart, transformEnd) { console.log (transformStart) console.log (transformEnd) currentAnimation = elem.animate ( [ { transform: transformStart }, { transform: transformEnd } ], { duration: 2000, fill: "forwards" } ) } function shiftLeft() { move ("translateX(400px)", "translateX(0)") } function shiftRight() { move ("translateX(0)", "translateX(400px)") }
Wenn die Rechts- / Links-Buttons schnell nacheinander gedrückt werden, sehen wir, dass die jeweils andere Richtung nicht sofort an Ort und Stelle ausgeführt wird, sondern erst an den offiziellen Startpunkt springt. Was da tatsächlich passiert, kann in der Firefox-Console unter Animationen beobachtet werden.

pause() und cancel()
Ein vorgelagertes Pausieren kann dieses unerwünschte Verhalten beenden. getComputedStyle(elem) liefert die aktuellen CSS-Stile des animierten Elements. Der neue Startpunkt kommt vom Stil transform des Keyframes. Erst dann wird die Animation gecancelt (wobei der Browser die Ressourcen freigibt) und die neue Animation gestartet.
Und noch ein Einwand: Wenn die Animation z.B. nach der halben Laufzeit (~1000 ms) beendet wird, läuft die gegenläufige Animation für die volle Dauer und das Element bewegt sich langsamer. currentAnimation.effect.getComputedTiming() liefert die neuen Ausgangswerte und die neue Dauer berechnet sich mit
duration = activeDuration - progress * activeDuration
const elem = document.querySelector("#circle"); let currentAnimation; function move (transformEnd) { currentAnimation?.pause(); let transformStart = getComputedStyle (elem).transform; let duration = 2000; if (currentAnimation) { const timing = currentAnimation.effect.getComputedTiming(); const activeDuration = timing.activeDuration; const activeProgress = timing.progress; duration -= activeDuration - activeProgress * activeDuration; } currentAnimation?.cancel(); currentAnimation = elem.animate ( [ { transform: transformStart }, { transform: transformEnd } ], { duration: duration, fill: "forwards" } ) } function shiftLeft() { move ("translateX(0)") } function shiftRight() { move ("translateX(400px)") }
finish()
Das Javascript Web Animation Api bietet mehrere Optionen, um das Ende einer Animation festzustellen.
currentAnimation.onfinish = () => console.log("Animation beendet");
// oder mit Promise
currentAnimation.finished.then(() => console.log("Animation beendet"));
Das Promise löst eine Fehlermeldung aus, die abgehandelt werden muss.
currentAnimation.finished
.then (() = console.log ("Animation beendet"))
.catch ( error => console.log ("Animation gecancelt", error));
//Und natürlich können wir async/await benutzen
try {
await currentAnimation.finished;
} catch (error) {
console.log ("Animation gecancelt", error);
}