Javascript Web Animation API – finish, cancel

Web Animation API finish, cancel

Das Web Animation API kann mittels Animation.onfinish feststellen, dass eine Animationen vollständig durchgeführt oder ob die Animation gecancelt wurde.

An jeder Stelle der Animation können aktuelle Werte der Animation abgefragt werden, um Verhalten zu ändern und auf das Verhalten anderer Elemente zu reagieren.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

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.

firefox-animation-console

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)")
}

dot 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);
}