Javascript Animationen mit requestAnimationFrame

Javascript Animationen mit request Animation Frame

requestAnimationFrame ruft vor jedem erneuten Rendern (»Refresh«) des Browserfensters die Animations-Funktion auf und erzeugt so einen weichen Übergang von einem Frame zum nächsten. Mit requestAnimationFrame anstelle von setInterval oder setTimeout übernimmt der Browser die Schnittstelle und optimiert das Verfahren, so dass Animationen runder, ohne Ruckeln und effizienter ablaufen.

Wenn der Benutzer zu einem anderen Tab wechselt, kann der Browser die Animation pausieren, um die CPU weniger zu belasten. Schön für unsere mobilen Geräte …

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

requestAnimationFrame vs setInterval

setTimeout und setInterval sind altgediente Techniken in der Animation mit Javascript. Sie verändert das animierte Element alle paar Millisekunden.

setInterval
function animate () {
    // Berechnen 
}

setInterval (animate, 1000);
setTimeout
function animate () {
    setTimeout (animate, 500);
    // Berechnen
}
animate();

setInterval() erwartet zwei Parameter oder Argumente: die Funktion, die bei jedem Schritt der Animation aufgerufen wird, und das Zeitinterval, in dem die Funktion für die Animation aufgerufen wird.

Aber setInterval() ist ineffizient. Wenn der Benutzer ein anderes Tab im Browser öffnet, läuft die Animation weiter. requestAnimationFrame ist effizienter.

requestAnimationFrame vs CSS-Animationen

CSS-Animationen sind mächtig, aber ihnen fehlen die Ereignisse, die eine Aktion starten oder beenden: CSS erkennt zwar ein Hovern mit der Maus, aber nicht das Touch des Fingers und Mausklicks nur auf wenigen Elementen (wie Radiobuttons). Auch bei komplexen Ketten (z.B. »starte Aktion, wenn eine andere Aktion abgelaufen ist«) bleibt CSS außen vor. Für Aktionen wie Stop, Pause und Resume eignet sich requestAnimationFrame besser.

Für komplexe Animationen haben wir heute auch das Web Animation Api, das eine CSS-ähnliche Notation nutzt, und den Start einer Aktion abhängig vom Zustand anderer Aktionen macht. Dennoch bleibt requestAnimationFrame die Wahl bei canvas-Animationen, denn im canvas-Element herrscht nicht das Document Object Model, sondern canvas basiert auf Pixeln.

Frame-Rate

Bei Animationen mit setTimeout oder setInterval kann das Script die aktuelle Frequenz der Frames nicht feststellen. requestAnimationFrame wird per Vorgabe 60 mal pro Sekunde aufgerufen – mehr ist selten nötig (oder besser: möglich), denn 60 Hz ist die Refresh-Rate der meisten Browser (oder Zeitrahmen von 16.7ms).

In Animationen mit requestAnimationFrame kann die Browser die Refresh-Rate reduzieren, wenn die Animation in einem Hintergrund-Tab läuft, um den Energieverbrauch zu senken.

requestAnimationFrame agiert anders als setInterval. Statt einen Timeout mit einer Verzögerung von 16.7ms in einer Schleife immer wieder aufzurufen, feuern die Browser ein Event, sobald das System wieder einen Frame rendern kann.

Syntax

Die Syntax von requestAnimationFrame() gleicht der Syntax von setTimeout(), da requestAnimationFrame wiederholt aufgerufen wird. Nur ein Timeout oder Interval wird nicht benötigt.

Wenn der Screen neu gerendert werden soll, wird requestAnimationFrame mit dem Name der Funktion aufgerufen, in der die Veränderungen und Berechnungen durchgeführt werden (aka Callback).

requestAnimationFrame(callback);
animierte Lokomotive
var iterationCount = 0;
var repeater;

function runlock () {
   easing = easeInQuad(iterationCount, 0, width, 300);
   lok.setAttribute ('style','left: ' + easing + 'px');
   iterationCount++;

   if (iterationCount > 250) {
      cancelAnimationFrame(repeater);
   } else {
      repeater = requestAnimationFrame(runlock);
   }
}

runlock();

Die Lok läuft langsam an und wird schneller: Hier noch mit den Gleichungen von Robert Penners, die von Kipura für Javascript portiert wurden. Da ist das Javascript Web Animation Api weiter: Easing für Javascript Animationen.

requestAnimationFrame ist keine Schleife und kein Timer, sondern muss jedes Mal aufgerufen werden, wenn die Animation etwas ändert. Bis die Animation endet, muss requestionAnimationFrame immer wieder durch die Callback-Funktion aufgerufen werden.

Das ist also das »Skelett« der Animation:

function animate() {
 
   // Berechnen / Verändern = Animieren
 
   requestAnimationFrame(animate);
}
animate();

requestAnimationFrame mit Parametern

request Animation Frame wird mit einer Callback-Funktion aufgerufen. Wenn Parameter übergeben werden, kann die Callback Function auch eine anonyme Funktion sein, die wiederum die benötigten Parameter enthält.

function moveCurtain (curt, height) {
    easing = easeInOutQuart(step, height, -300, 90);
    step++;

    if (easing < 1) {
        cancelAnimationFrame (repeater);
        step = 0;
    } else {
        curt.setAttribute('height',easing);
        repeater = requestAnimationFrame (function () {
            moveCurtain (curt, easing);
        });
    }
}

function.bind() ist ein weiterer Mechanismus, um requestAnimationFrame mit Parametern aufzurufen. bind erzeugt eine neue Funktion, die this als ersten Parameter an bind() übergibt.

Animiert einfache Wellen in versch. Blautönen
function move ( elem, timestamp) {
	
	// Berechne left und y
	
	elem.setAttribute("transform", "translate(" + left + " " + y +")");
	requestAnimationFrame (move.bind (0,elem));
};

for (let i=0; i<waves.length; i++) {
	requestAnimationFrame(move.bind (0, waves[i]));
}

Javascript animate () – Web Animation API

Mit animate () ist neben setTimeout, setInterval und requestAnimationFrame eine weitere Technik für Animationen auf den Plan getreten. Das Web Animation API mit animate() lehnt sich an CSS-Keyframes-Animationen an und eignet sich besonders für die Ablaufsteuerung von komplexen Objekten. requestAnimationFrame bleibt weiterhin die Basis für Canvas-Animationen.