EaselJS: Animation and Ticker

Synopsis: Create a simple programmatic animation, and learn about the Ticker class.
Topics: animation, Ticker, setFPS, useRAF, getTime, setPaused, requestAnimationFrame, Stage.update, time based animation
Target: EaselJS v0.5.0

Animation Basics

Animationen ändern die visuellen Eigenschaften eines Objekts innerhalb der Zeit. Es gibt einige Tweening Klassen, die dieses vereinfachen (wie TweenJS oder TweenLite). In diesem Tutorial geht es allerdings um die grundsätzlichen Konzepte,ohne diese Klassen zu benutzen.

Wenn man den folgenden Code in ein Zeitinterval setzt wird der circle sich nach rechts bewegen:

Das ist einfach, aber wie setzt man am besten ein Zeitinterval? Man kann seine eigene Implementierung einsetzen mit setInterval, setTimeout, oder requestAnimationFrame. Damit arbeitet EaselJS perfekt, sofern man stage.update() aufruft, um die Display Liste zu aktualisieren..

Um die Sache zu vereinfachen, gibt es in EaselJS eine Ticker Klasse, welche die Anwendung mit einem regelmäßigen Herzschlag (tick) versorgt. es unterstützt Pausen, time deltas und wraps (Hüllen), sowohl für setTimeout und auch requestAnimationFrame, so dass man beides abwechselnd einsetzen kann.

Ticker

Die Ticker Klasse unterstützt ein einfaches statisches Interface, was bedeutet man erzeugt keinen neuen Ticker mit new Ticker() für verschiedene Objekte. Man fügt einfach einen Listener hinzu mit addListener(listener). Der Listener kann eine Funktion sein oder ein Objekt mit einer definierten tick Funktion.

Im unten stehenden Code wird window als Listener hinzugefügt. Es wird eine tick Funktion definiert, die 20 mal pro Sekunden aufgerufen wird. Das ist die Standard Framerate.

Man kann ganz einfach die Standard Framerate ändern, entweder in dem man ein Intervall setzt (die Zeit zwischen den Ticks) oder indem man die Framerate setzt (die Zahl der Ticks pro Frame).

Nun wird alles mal kombiniert, um einen circle mit 30 Frames pro Sekunde über die Bühne laufen zu lassen. Vergessen Sie nicht den Aufruf von stage.update() am Ende jedes ticks damit die Veränderungen auf der canvas gezeichnet werden. Überprüfen Sie den Quellcode von simple.htm.

Time based animation

Für viele Anwendungen ist es sinnvoll, die Animation unabhängig von der Framerate anzulegen. Dadurch ermöglicht man eine dynamische Änderung der Framerate, was sicherstellt, dass die Animationen in gleicher Zeit ablaufen, sogar wenn sie auf einem langsamen Gerät laufen, welches die Framerate nicht einhält.

Ticker macht zeitbasierte Animationen einfach, indem der Listener einen Parameter übergibt, der anzeigt welche Zeit, seit dem vorigen Tick vergangen ist. Außerdem stellt er eine getTime Methode zur Verfügung, welche die Zeit bereitstellt, die seit der Initialisierung des Ticker vergangen ist.

Man kann seine Animationen zeitbasiert anlegen, indem man einfach die vergange Zeit anfordert, während man die Eigenschaften ändert.

Nun kann man die Framerate ändern und der circle wird in der gleichen Zeit die canvas zu überqueren (plus minus ein paar Millisekunden).

Wenn Sie in dem obenstehenden Demo die FPS ändern, bewegt sich der rote Kreis mit der gleichen Geschwindigkeit, während der blaue Kreis seine Geschwindigkeit relativ zur Framerate einhält. Außerdem kann man beobachten wie sich der rote Kreis bei einer Framerate von 20fps etwas schneller bewegt als der blaue Kreis. because it accounts for frames that take slightly longer than the expected 50ms.

Pausing

Außerdem unterstützt Ticker die Möglichkeit alle Animationen anzuhalten.Standardmäßig sind alle Listener die man dem Ticker zuweist anhaltbar, indem man Ticker.setPaused(true); aufruft. Das stoppt den tick Aufruf aller anhaltbaren Ticker Listener.

Außerdem kann man einen Listener als nicht anhaltbar registrieren, indem man den zweiten Parameter auf false setzt:

Diese Listener "ticken" weiter, auch wenn der Ticker angehalten wird. Außerdem wird beim Aufruf ein zweiter Parameter übergeben, der anzeigt, ob der Ticker angehalten wurde.. Um ein Beispiel zu nennen, auf diese Weise kann man UI Animationen weiterlaufen lassen auch wenn ein Spiel angehalten wurde.

Zum Abschluß folgendes, die getTime Methode akzeptiert einen pauseable Parameter, der die gesamte Zeit übergibt, die darauf beruht.

Spielen Sie im folgenden Demo mit der hin und her schaltbaren Pause und beobachten Sie, wie der rote "pausable" Kreis anhält, währen der grüne "unpausable" es nicht tut. Außerdem kann man sehen wie die Gesamtzeit der "pausable" Zeit anhält wenn der Ticker angehalten wurde.

 

onTick

Wenn man stage.update( aufruft, ruft es onTick() auf jedem Display Objekt auf, bevor es auf die Bühne gezeichnet wird. Jeder Parameter der update() zugewiesen wird, wird den onTick() Handlers übergeben. Das ermöglicht Ihnen Ihre Animationen im Bezug auf das Display Objekt zu handhaben.

Man kann der stage auch direkt einen Listener zum Ticker zuweisen, denn Stage hat eine tick Methode die auf update verkürzt (shortcut). Sie werden es eher selten einsetzen, aber es kann eine praktische Methode für kurze Tests sein. Schauen Sie sich den Quellcode des Beispiels an onTick.html

requestAnimationFrame

Die meisten modernen Browser unterstützen eine neu Art der Animation in Bezug auf die API, man nennt es requestAnimationFrame. Es bezieht Vorteile aus gleichzeitigen Programmabläufen und Bildschirmaktualisierungen. Es drosselt die Framerate von Inhalten im Hintergrund (nicht focussierter tab) und reduziert die CPU und Speichernutzung.

Wenn Sie Ticker.useRAF = true setzen wird der Ticker requestAnimationFrame nutzen, sofern es unterstützt wird oder auf setTimeout zurückfallen, wenn nicht.

createjs.Ticker.useRAF = true;

Wenn man das macht, sollte man die Framerate auf einen Divisor von 60 setzen (z.B.: 15, 20, 30, 60), um ein möglichst gleichmäßiges Ergebnis zu erzielen.

Performance

Erinnern Sie sich dass eine größere Framerate nicht immer eine flüssigere Animation erzeugt. Eine niedrige Framerate benötigt weniger CPU und kann eine gleichmäßigere Darstellung erzeugen. Finden Sie die richtige Balance für ihr Projekt.

Wenn Sie Ihre wirkliche Framerate herausbekommen möchten, rufen Sie Ticker.getMeasuredFPS() auf, um die wirkliche durchschnittliche Framerate der letzten Sekunde zu erhalten.

TweenJS

Wenn Sie viel mit Animationen arbeiten wollen, sollten Sie vielleicht TweenJS oder eine andere tweening Bibliothek erkunden. Mit einfachen Befehlen kann man Tweening Eigenschaften über die Zeit hinweg bestimmen oder Animations-Sequenzen erstellen.