CSS, HTML und Javascript mit {stil}

Javascript Animationen mit requestAnimationFrame

Javascript Animationen requestAnimationFrame

Mit requestAnimationFrame anstelle von setInterval oder setTimeout für Animationen übernimmt der Browser die Schnittstelle und optimiert das Verfahren, so dass Animationen weicher 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 …

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 Animationsschritt 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.

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);
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: Easing für Javascript Animationen – Robert Penners Original-Gleichungen, von Kipura für Javascript portiert.

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

requestAnimationFrame 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.

function move ( elem, timestamp) {
	
	// Berechne left und y
	
	elem.setAttribute("transform", "translate(" + left + " " + y +")");
	requestAnimationFrame (move.bind (0,elem));
};

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

requestAnimationFrame – Browser-Support

IE9 war der letzte Microsoft-Browser, der requestAnimationFrame nicht unterstützt. Am 12.1.2016 hat Microsoft den Support für IE9 für die meisten Betriebssysteme eingestellt.

IE10, Safari ab Version 9, Chrome ab V45, Firefox ab 43, Opera ab 34 unterstützen requestAnimationFrame bereits.