Animations-Methoden in Javascript
Für Animationen werden meist Libraries oder ganzen Frameworks eingesetzt, aber die Grundlagen von Animationen mit Javascript sind die Voraussetzung für das Verständnis der verzwickten Logik hinter Bewegungsabläufen und Reaktionen.
Javascript stellt drei Klassiker und eine modernere Technik für Animationen:
- setTimeout ()
- setInterval () wiederholt Anweisungen in einem Interval.
- Beim requestAnimationFrame () übernimmt der Browser die Schnittstelle und optimiert das Verfahren.
- Javascript Web Animation API ist die jüngste Option und lehnt sich eng an CSS-Animationen an.
Die Grundidee der Animation mit Javascript: Mach ein Element Bild für Bild in schneller Folge sichtbar oder unsichtbar, bewege es oder verändere sein Aussehen nach und nach. Dabei entsteht eine Sequenz von Einzelbildern oder Frames, die schnell genug aufeinander folgen, dass die Bewegung fließend und natürlich wirkt.
Lemmings, das Computerspiel des Entwicklers DMA Design (1991)
Delay – Verzögerung mit setTimeout
Eine kurze Verzögerung ist der einfachste Fall. So können z.B. Bilder nachträglich geladen und mit einer kurzen Verzögerung eingespielt werden.
setTimeout (function() { slides[0].classList.add("fadeIn") }, 200); setTimeout (function() { slides[1].classList.add("fadeIn") }, 600);
Keine Animation im eigentlichen Sinn, sondern nur eine Verzögerung bevor die Animation startet. Das können wir heute schon allein mit CSS umsetzen.
.fadeIn { transition-property: opacity; transition-duration: 1s; transition-delay: 1s; }
setTimeout
Javascript window.setTimeout(action, timeout) gibt an, dass Anweisungen nach einer bestimmten Zeit timeout (angegeben in Millisekunden) ausgeführt werden.
let ani = setTimeout ( action, timeout ); | | | | | +---> Zeit in Millisekunden | | bis zum Aufruf der Anweisungen | | | +---> Anweisung oder Funktionsaufrufe +---> optionale Referenz, mit der setTimeout abgebrochen werden kann
setTimeout(action, n) startet Anweisungen mit einer Verzögerung von timeout Millisekunden.
time = 6; function countdown () { time -= 1; number.firstChild.nodeValue = time; if (time > 0) { let ani = setTimeout( countdown, 1000); } } countdown();
Javascript setTimeout() führt die Anweisungen exakt einmal aus (und der Timer ist nicht besonders exakt) und dann nie wieder. Darum wird setTimeout hier im Beispiel innerhalb der Funktion countdown wiederholt aufgerufen, bis die Bedingung (time > 0) nicht mehr stimmt.
setTimeout async await
Asynchron bedeutet, dass die Funktion sozusagen parallel zu den folgenden Anweisungen durchgeführt wird – die auf setTimeout folgenden Anweisungen also nicht blockiert.
Das komplette Javascript stopt nicht, um die Ausführung der Anweisungen abzuwarten. Das Script läuft weiter, denn setTimeout() ist asynchron. Das Programm wird weiter abgearbeitet, während der Timer noch schläft und auf sein vorprogrammiertes Erwachen wartet.
Erst ES7 versetzt asynchrone Aktionen mit den Schlüsselwörtern async / await in eine synchron-ähnliche Funktion. Eine Funktion, die mit async gekennzeichnet wird, hält die Ausführung an.
const wait = seconds => { return new Promise ( resolve => setTimeout (resolve, seconds * 1000) ) } const waitFive = async () => { document.querySelector(".count").textContent = "0"; await wait (5); document.querySelector(".count").textContent = "5"; } document.querySelector(".startCount").addEventListener ("click", () => { waitFive () })
async / await vereinfachen die asynchrone Programmierung deutlich und die immergrünen Browser unterstützten async / await bereits. IE11 bleibt außen vor.
clearTimeout()
Um die Anweisung wiederholt durchzuführen, muss das Skript wiederholt aufgerufen werden – z.B. rekursiv wie im Beispiel oder in einer Schleife.
Die Funktion setTimeout() gibt einen einfachen Wert zurück – einen Verweis auf den Timeout. Die Referenz auf setTimeout() wird benötigt, um den Timeout abzubrechen und die Ausführung der Anweisungen zu unterbinden.
Javascript clearTimeout() cancelt den Aufruf von setTimeout().
window.clearTimeout(ani);
setTimeout() wird eher selten für Animationen benutzt, sondern für einfache verzögerte Aktionen, da setTimeout() die Aktion nur einmal durchführt. Statt selber Schleifen oder rekursive Funktionen einzusetzen, greift man bei Animationen mit schrittweisen Änderungen lieber zu setInterval().
setTimeout mit Parametern
Wenn die aufgerufene Funktion selber Parameter hat, könnten die Parameter auch in setTimeout übergeben werden. Diese Möglichkeit gab es immer schon, aber sie wurde nie von Internet Explorer unterstützt und geriet in Vergessenheit.
let optcounter = document.getElementById('optdown'); let optnumber = document.getElementById('optnumber'); let optcircle = document.getElementById('optcircle'); startbutton.onclick = counter.onclick = function () { function countdown (time,hue) { time -= 1; hue += 60; number.firstChild.nodeValue = time; optcircle.setAttribute('stroke','hsl(' + hue + ',85%,60%)'); optnumber.setAttribute('fill','hsl(' + hue + ',85%,60%)'); if (time > 0) { setTimeout( countdown, 1000, time, hue); } } countdown(6, 30); }
Ab IE10 können setTimeout und setInterval mit Parametern aufgerufen werden.
Die Funktion könnte auch mitsamt Parametern in Hochkommas an setInterval übergeben werden. Dann wird die Funktion – auf gleiche Weise wie eine einzelne Anweisung – evaluiert.
let timer = setInterval("slideshow(opt1,opt2)",500);
Das gilt aber als ausgesprochen unschicklich und ist unsicher (»eval«). Stattdessen kann setInterval mit einer anonymen Funktion aufgerufen werden.
setTimeout rekursiv
Die Verzögerung bewirkt nicht, dass die Anweisungen alle n Millisekunden aufgerufen werden, sondern dass die Funktion einmal mit einer Verzögerung von n Millisekunden aufgerufen wird.
let timerId = setTimeout ( function tick() { let counter = parseInt(document.getElementById("counter").textContent); document.getElementById("counter").textContent = counter - 1; if (counter > 1) timerId = setTimeout(tick, 1000); }, 1000);
Easing: natürliche Bewegungsabläufe
Easing hat Animationen mit Flash so elegant gemacht, wird bei Animationen mit jQuery mitgeliefert, CSS macht es mit transition und keyframes, aber hat Javascript viele Jahre gefehlt. Erst das Web Animation Api setzt Easing für natürliche Bewegungsabläufe ein: Easing – Beschleunigen und langsames Auslaufen von Bewegungen.
Die meisten Javascript-Animationen verändern CSS-Eigenschaften – CSS transition und Keyframe-Animationen bringen Easing-Optionen mit.
easeIn(currentIteration, begin, change, duration);
change = finish - begin
CSS transition statt Javascript
Die Kombination aus CSS3 transition, Keyframe-Animationen und Javascript vereinfacht heute Animationen und macht komplexe Abläufe möglich. Neue Javascript Methoden wie classList triggern Aktionen, denn CSS hat nur wenige Events, die eine Animation auslösen.
Der Ruf, dass reine CSS Animationen und Transformationen performanter als Javascript wären, rührt aus jQuery-Animationen: jQuery war nicht für Animationen gedacht.