senäh

17senäh und so…

HTML/CSS/JS
23. Mai 2012
Kommentare: 0

TweenLite/TweenMax für JavaScript veröffentlicht – Yeehaa!

Kategorien: HTML/CSS/JS | 23. Mai 2012 | Kommentare: 0

Alte Flasher-Hasen wissen worauf sie sich freuen können: die Koryphäe aller Tweening-Frameworks findet ihren Weg nach JavaScript. Die Rede ist von der GreenSock Animation Platform (GSAP), besser bekannt als TweenLite/TweenMax. Nach meiner Erfahrung ist Tweening das Salz in der Suppe der AS3 Programmierung. Umso erstaunter war ich, dass Tweening auf anderen Plattformen stiefmütterlich behandelt wird. Das habe ich auf meinem kurzen Ausflug in XNA gemerkt (hier mein verzweifelter Aufruf im App Hub Forum), aber auch in HTML5. Dabei habe ich schon bei einem meiner ersten Canvas Experimente Tweens benötigt! Damals habe ich tween.js von sole verwendet. Eine recht gute Alternative, aber irgendwas habe ich vermisst. Das ändert sich nun. Hoffentlich… 😉

Hinweis: Wer schon weiß, was Tweens sind, kann das Einleitungsgedöns ruhig überspringen und ganz nach unten zu den Beispielen scrollen.

Tweening. WTF?!

Wer bisher nur Bahnhof verstanden hat, bekommt jetzt eine kleine Zusammenfassung. Tweening ist eine Animationstechnik. Man nehme ein Tweening-Framework, gebe einen Startwert A und einen Startwert B an, sowie eine Zeit. Anschließend berechnet das Tweening-Framework alle Zwischenwerte von A nach B innerhalb dieser Zeit (zwischen = between).

Ein Beispiel: Stellt euch eine Bowlingkugel vor. Ihr werft sie an Punkt A und sie kommt bei den Kegeln an Punkt B an. Wenn ihr sagt, die Kugel benötigt dafür drei Sekunden, dann spuckt euch das Tweening-Framework eine 3sekündige Animation aus, in der die Bowlingkugel vom Spieler zu den Kegeln rollt.

Das ist aber natürlich noch nicht alles. Die Berechnung der Zwischenwerte kann durch die Angabe einer Easing-Funktion verfeinert werden. Sie beschreibt wie die Zwischenwerte im Verhältnis zur vergangenen Zeit berechnet werden. So könnt ihr sagen, dass sich zu Beginn der Animation die Zwischenwerte erst langsam Richtung Endwert entwickeln und dann immer schneller. Ein gutes Beispiel wieder aus dem Alltag: Ihr lasst einen Ball von der Höhe A auf die Höhe B (für Boden ;)) fallen. Durch die Erdanziehung wird der Ball immer schneller. Je länger er fällt, umso mehr Strecke legt er in einem bestimmten Zeitpunkt zurück. Genau das könnte man mit einer Easing-Funktion beschreiben.

Ein Tweening-Framework baut um diesen Vorgang aber noch viel mehr Funktionalitäten auf. So können Tweens kombiniert werden (Bsp.: Einen Ball werfen. Er fliegt nach vorne und fällt gleichzeitig.), Tweens rückwärts abspielen (Bsp.: Ein Ball prallt vom Boden ab und fliegt wieder nach oben.), Tweens können geloopt/pausiert/gestoppt werden, werfen Events (Tween complete!) und und und…

Tweens sind einfach awesome!

TweenLite/TweenMax

Nun aber zum eingangs erwähnten Framework von GreenSock: TweenLite/TweenMax. Ich habe diese Frameworks bestimmt in 80% meiner alten Flash-Projekte eingesetzt und kenne auch keinen Flasher, der die Frameworks nicht wenigstens einmal gesehen hat. Auch hier auf senäh findet sich so ein Projekt. Im Spiel Ginger Jump habe ich die fliegenden Ennos mit TweenMax realisiert.

Gaaaaaanz kurz noch was zur Lizenz bevor wir uns ein praktisches Beispiel anschauen: TweenLite/TweenMax ist für freie Projekte ebenfalls frei und für kommerzielle-aber-frei-zugängliche Projekte auch. Wie bitte? Eine Microsite zu einem Film gilt als kommerzielle Seite (wirtschaftlich betriebene Werbeseite), aber sie ist für jeden frei zugänglich. Schließlich soll ja jeder die dort enthalten Infos und Trailer sehen. Erst wenn eure Internetseite/Spiel/whatever nur gegen Bezahlung zugänglich werden (z.B. in Form einer App) benötigt man eine spezielle Lizenz um TweenLite/TweenMax verwenden zu dürfen. (Disclaimer: Alle Angaben ohne Gewähr…)

Nun aber los! Als ersten müssen wir TweenLite/TweenMax installieren. Geht auf GSAP12 (im Augenblick als Beta) und wählt oben rechts JavaScript aus:

Announcing GSAP v12, now with tangy JavaScript flavor!

Announcing GSAP v12, now with tangy JavaScript flavor!

Cool. Nun zu einer Kurzübersicht zum Framework. Die volle (gute) Dokumentation findet ihr hier. Wie ihr bestimmt schon mitbekommen habt, gibt es zwei Versionen des Tweening-Frameworks: Lite und Max. Lite enthält die Grundfunktionalitäten, welche individuell durch Plugins erweitert werden können. Dadurch wird die Dateigröße klein gehalten. TweenMax enthält alle Funktionen von TweenLite PLUS alle Plugins PLUS weitere Extrafunktionen. Zusätzlich zu TweenLite/TweenMax gibt es noch TimelineLite respektive TimelineMax. Sie dienen dazu einzelne Tweens zu kombinieren und sequenzieren (- ich erinnere hier wieder an das Beispiel mit dem geworfenen Ball). Wenn ich den Source Code richtig deute, enthält die TweenMax.min.js bereits TimelineMax.

Und wie sieht das dann aus?

Objekte tweenen – Beispiele

Steigen wir endlich in den Code ein. Als Ausgangspunkt für die ersten Beispiele benötigen wir einen Kreis auf einem Canvas (mehr Infos zum Zeichnen auf ein Canvas):

Die wichtigste Zeile dafür lautet: context.arc(70, 50, 30, 0, Math.PI * 2, true); // (x, y, radius, startAngle, endAngle, clockwise). Tweenen wir doch mal die x Position des Kreises. Dazu müssen wir die Werte, die wir tweenen wollen, in ein eigenes Objekt überführen. Der einfachheithalber mache ich das für jeden Wert, den die Funktion context.arc() benötigt:

var circle = {
    x: 70,
    y: 50,
    radius: 30,
    startAngle: 0,
    endAngle: Math.PI * 2,
    clockwise: true
};

Anschließend verschieben wir den Zeichnen-Aufruf in eine eigene Funktion:

var drawCircle = function() {
    context.clearRect(0, 0, canvas.width, canvas.height);

    context.fillStyle = "#FF0000";  // color
    context.beginPath();
    context.arc(
        circle.x,
        circle.y,
        circle.radius,
        circle.startAngle,
        circle.endAngle,
        circle.clockwise);
    context.closePath();
    context.fill();
};

Nun bindet ihr die TweenMax.min.js ein und habt danach Zugriff auf das neue globale Objekt TweenMax. TweenMax besitzt die statische Funktion to(), welche drei Parameter entgegen nimmt: das zu tweenende Objekt, die Dauer in Sekunden und ein Konfigurationsobjekt. („Tweenende“ ist auch ein beschissenes Wort, oder?) Das Konfigurationsobjekt besitzt die neuen Endwerte des Objekt und kann zusätzlich mit EventHandlern und/oder Steuerungsmöglichkeiten (loopen, umkehren, etc.) versehen werden. Wir gebe den neuen x Wert an und die Funktion drawCircle() als onUpdate-Handler. D.h., dass bei jedem Update des Tweens die Funktion drawCircle() aufgerufen wird, um unseren Kreis zu zeichnen:

TweenMax.to(circle, 1, {x: 250, onUpdate: drawCircle});

Das war’s! Schon haben wir unsere erste Animation (- ihr müsst ggf. die Seite neuladen, um die Animation zu sehen):

Mit repeat: -1 im Konfigurations-Objekt gebt ihr an, dass die Animation unendlich wiederholt werden soll (- mit einer 3 würdet ihr angeben, dass sie 3mal wiederholt werden soll, usw.). Ich habe auch die Dauer etwas verlängert, damit wir die Animation besser sehen:

Fügen wir jetzt mal eine Easing-Funktion hinzu. Dies geht mit der Eigenschaft ease im Konfigurationsobjekt, der ihr eine der zahlreichen vorgegebenen Easing-Funktionen übergebt, z.B. Power4.easeIn (- die vollständige Liste an möglichen Easing-Funktionen findet ihr in der Dokumentation). Hier sieht man schön, dass sich der x Wert zunächst kaum verändert und zum Ende hin dafür sehr schnell:

Natürlich können wir auch mehrere Werte auf einmal tweenen. Hier tweene ich zusätzlich noch den y Wert:

 Beide Werte werden jetzt allerdings mit der gleichen Easing-Funktion getweent. Möchte ich dies nicht, kann ich für jeden Wert, der geändert werden soll, einen eigenen Tween erstellen. Ich tweene den y Wert jetzt mit der Easing-Funktion Bounse.easeIn, welches ein leichtes hüpfen erzeugt. Da ich nun aber zwei Tweens verwenden, muss ich bei einem den onUpdate-Handler heraus nehmen, um nicht unnötig zweimal die gleiche Funktion aufzurufen:
Aber irgendwie ist das nicht so schön gelöst. Ich habe hier zwei Tweens, die zur gleichen Animation gehören. Einmal habe ich einen onUpdate-Listener und einmal nicht: inkonsistent! Außerdem vergebe ich zweimal für repeat den Wert -1: DRY! Hier hilft TimelineMax. Ich erzeuge eine neue Timeline-Instanz, welche als Konfigurationsobjekt alle Werte erhält, welche für alle Tweens innerhalb dieser Timeline gelten soll. Sprich: TimelineMax erhält einen onUpdate-Handler und für repeat den Wert -1. Anschließend kann ich der Timeline neue TweenMax Instanzen hinzufügen, welche selbst keinen onUpdate-Handler mehr haben müssen und auch keinen Wert für repeat angeben müssen (- es sei denn ich möchte das aus irgendeinem Grund). Die Animation sieht genau so aus wie vorher, aber wenn ihr euch den Code anschaut, seht ihr, dass er aufgeräumter und übersichtlicher ist (IMO):
Wenn ich jetzt etwas Feintuning bei der Start- und Endwerten und dem Easing betreibe, erhalte ich meine zuvor beschriebene Ball-Wurf-Animation:
Achja… ich kann übrigens jeden numerischen Wert tweenen. Verändern wir doch mal den Radius, so dass der Ball immer kleiner wird:
Oder wie wäre es, wenn wir den Endwinkel verändern? Ihr müsst übrigens nicht bei jedem Tween in der Timeline die gleiche Zeitdauer einstellen. Ihr könnt auch die Zeitdauer extrem verkürzen (z.B. auf 0.2 Sekunden) und dafür für genau diesen Tweenrepeat erhöhehen (z.B. auf 20, so dass wieder 4 Sekunden herauskommen). Mit yoyo: true im Konfigurationsobjekt legt ihr übrigens fest, dass ein Tween bei einer Wiederholung nicht einfach wieder von vorne beginnt, sondern erst rückwärts abläuft. So kann bspw. man eine Art flattern simulieren, welches unseren Ball mit etwas Phantasie fast wie ein Schmetterling aussehen lässt 🙂
Und ja, man kann nicht nur JavaScript-Objekte, sondern auch DOM-Elemente/CSS-Werte animieren! Dazu müssen nur alle CSS-Werte in einem eigenem Objekt liegen, welches wiederum im Konfigurationsobjekt unter css liegt:
Und hey! GreenSock beachtet sogar die Browserkompatibilität! Die Transformationsmöglichkeiten, die mit CSS3 eingeführt wurden, sind bspw. durch Fallbacks bis runter zum IE6 einsetzbar. Dies scheint noch nicht komplett vollständig zu probieren (rotateZ funktioniert nicht…?), aber in 95% der Fälle. So lässt sich bspw. auch die Farbe tweenen:
Und das sollte für den Anfang reichen. Kleiner Tipp am Schluss: Alle Methoden sind chainbar.
Damit lassen sich doch schon ziemlich interessante Effekte erzielen oder? 🙂
Ein letzter noch, weil’s so schön war:
Und aus die Maus 😀

Autor: Pipo

...kommt ursprünglich aus der Designerecke, ist aber im Laufe seines Studiums in die Webentwicklung gestolpert. Kann sich seit dem nicht so richtig entscheiden wo er hingehört und wagt deswegen vielleicht die Flucht nach vorne in ein komplett neues Gebiet. Vielleicht Management? Niemand weiß es. Auch er nicht.