.. _ref-animation: ############################################################################### Animation ############################################################################### Animationen sind zeitgesteuerte Veränderungen einer Presentation. Maongo besitzt ein Animationssystem, das es erlaubt, komplexe Animationsabläufe in XML zu definieren. Die Animationen in Maongo sind zeitbasierend. Dies bedeutet, dass Animationen unabhängig von der Framerate, mit der die Presentation abgespielt wird, immer gleich lange dauern. .. note:: **Zeitlicher Ablauf einer Animation** Bei jedem Frameaufruf des Maongosystems werden in allen laufenden Animationen die aktuellen Animationswerte berechnet (zeitliche Position innerhalb der Animation, Werte der zu animierenden Eigenschaften etc.). Davon ausgehend werden auf den betroffenen Widgets die Werte gesetzt. Soll eine Animation über einen Zeitraum von 4 Sekunden die Position eines Widgets von 0 auf 100 verändern, so bedeutet dies bei einer Framerate von 10 Bildern pro Sekunde eine Veränderung von 2,5 Pixeln pro Frame:: 4 Sekunden à 10 Frames = 40 Frames; 100 Pixel / 40 = 2,5 Pixel Sollte die Presentation mit 20 Frames pro Sekunde laufen, beträgt die Veränderung pro Frame nur 1,25 Pixel. Die Gesamtdauer der Animation bleibt unverändert. Grundlagen ============================================================================================================ Eine einfache Animation lässt sich mit dem Element ```` definieren, mit dem sich Widget-Eigenschaften über einen Zeitraum hin verändern lassen. Beispiel:: Dieser Tween ändert die Widget-Eigenschaft ``Location``; er bewegt das Widget im Zeitraum von einer Sekunde von Position ``10,10`` zu Position ``100,100``. Die Animation wird durch das Setzen der Widget-Property ``AnimationControl`` auf den Wert ``"play"`` gestartet. Beispiel:: this.AnimationControl = "play"; Animationselemente, die in einem Widget definiert sind, laufen parallel ab, wenn die Animation auf diese Art und Weise gestartet wird. Das Widget ist somit implizit ein Animationscontainer vom Typ ```` (s.u.). Neben ```` gibt es weitere "Animationsbausteine": * ```` schaltet die Widget-Eigenschaften direkt um; * ```` dient zum Aufruf einer Action in einer Animation bzw. zum Verweis auf an anderer Stelle definierte Animationen; * ```` dient zum Erzeugen einer Pause in einer Animation; * ```` mittels eines Iterator lassen sich in einer Animation Listen mit Werten zur Verfügung stellen. Daneben stellt Maongo zwei Elemente zur Verfügung, mit denen sich Animationen gruppieren lassen: ```` und ````. Animationen innerhalb einer Sequence werden nacheinander, solche innerhalb einer Parallel-Animation gleichzeitig bzw. nebeneinander abgespielt. Beispiel:: Die beiden Tweens laufen nacheinander ab, das Widget ändert zunächst seinen Ort, dann seine Form. Die Gesamtduer der Animation ist zwei Sekunden. Beispiel:: Die beiden Tweens laufen parallel ab, Ort und Form werden gleichzeitig geändert. Die Gesamtdauer der Animation ist eine Sekunde. Beispiel:: Location und Shape werden gleichzeitig verändert, danach wird die Farbe von rot zu blau verändert. Das Beispiel zeigt auch, dass AnimationsContainer wie ``sequence`` und ``parallel`` ineinander geschachtelt werden können. Ein weiterer AnimationsContainer ist ````. Ein Iterator kommt immer dann zum Einsatz wenn innerhalb einer Animation eine Liste von Werten bzw. Widgets genutzt werden soll. Gemeinsame Attribute =============================================================================== Die folgenden Attribute gelten für alle Animations-Elemente (tween, switch, animation, wait, iterator, sequence und parallel): **name** (String) Bezeichnung des Elementes. Wird ``name`` benutzt, so müssen Animationen innerhalb desselben Containers eindeutig benannt sein. Der Name kann zum Aufruf der Animation in Skripten und für Lookups innerhalb der Anwendung genutzt werden. **target** (String, @, {...}) Pfad auf ein Ziel-Widget, an dem die Animation ausgeführt werden soll. Wird in der XML-Deklaration der Animation ein ``target`` gesetzt, so gilt dies für das Animation selbst und seine Kinder; setzen die Childanimationen selbst auch ein Target, so versucht die Animationsengine, im Namensraum des Parent-Targets das Child-Target aufzulösen. Default: Wird target nicht gesetzt, so ist das Parent-Widget der Animation das Ziel-Widget der Animation. Besonderheit: Ein per Skript übergebenes ``target`` wirkt nur, wenn auf der Animation noch kein ``target`` gesetzt ist. **duration** (String, @, {...}) Netto-Dauer der Animation, ohne Pausen, Wiederholungen, etc. Wird die ``duration`` nicht angegeben, bestimmen die Parent- oder Child-Animationen die Dauer des einzelnen Elements. Als Werte können hier alle Angaben vom Datentyp ``Time`` interpretiert werden. Siehe dazu :ref:`ref-types`. Default: ``1s`` (eine Sekunde) **delay** (String, @, {...}) Verzögerung bis zum Beginn der Animation. Eine Animation mit ``delay="2s"`` beginnt zwei Sekunden, nachdem sie gestartet wurde. Als Werte können hier alle Angaben vom Datentyp ``Time`` interpretiert werden. Siehe dazu :ref:`ref-types`. Default: ``0`` **count** (Integer, @, {...}) Anzahl der Wiederholungen einer Animation. Default: ``1`` **gap** (String, @, {...}) Zeit zwischen zwei Wiederholungen. Als Werte können hier alle Angaben vom Datentyp ``Time`` interpretiert werden. Siehe dazu :ref:`ref-types`. Default: ``0`` **loopitems** (List, @, {...}) Liste von Objekten, über die mit den Wiederholungen iteriert wird. Legt gleichzeitig die Anzahl der Wiederholungen auf die Länge der übergebenen Liste fest. Ist ``count`` zusätzlich gesetzt, so gilt count, und die Liste wird entsprechend verkürzt genutzt, bzw. es wird erneut von vorne iteriert, bis ``count`` Wiederholungen erreicht sind. **extdur** (String, @, {...}) Die (nach außen hin sichtbare) Dauer der Animation. Diese wird entweder aus der Dauer der einzelnen Bestandteile unter Berücksichtigung von Loops und Delays/Gaps berechnet, oder kann explizit gesetzt werden, um eine interne Verteilung der Gesamtzeit auf die beteiligten Animationen zu erreichen. Als Werte können hier alle Angaben vom Datentyp ``Time`` genutzt werden. Siehe dazu :ref:`ref-types`. Im folgenden Beispiel ist jeder einzelne Tween 4 Sekunden lang (2 Tweens mit jeweils 4 Sekunden Länge):: **loop** (String, @, {...}) Anzahl der Wiederholungen für diese Animation. Default: ``0`` Beispiel:: **ft**: (Action, @, {...}) f(t, dur), Animationsfunktion. Eine Animationsfunktion muss für die Übergabewerte ``t`` (aktueller Zeitpunkt) und ``dur`` (Gesamtdauer der Animation), die als Parameter übergeben werden, einen Wert zwischen 0 und 1 zurückliefern. Als mögliche Werte stehen vorgefertigte Funktionen zur Verfügung:: LinearNone, LinearIn, LinearOut, LinearInOut, QuadIn, QuadOut, QuadInOut, CubicIn, CubicOut, CubicInOut, QuartIn, QuartOut, QuartInOut, QuintIn, QuintOut, QuintInOut, BounceIn, BounceOut, BounceInOut, BackIn, BackOut, BackInOut, CircIn, CircOut, CircInOut, ElasticIn, ElasticOut, ElasticInOut, ExpoIn, ExpoOut, ExpoInOut, SineIn, SineOut, SineInOut Default: ``LinearNone`` Es können auch Referenzen auf eigene Actions übergeben werden (Beispiel 2). Beispiel 1:: Beispiel 2:: return Math.pow(t/dur, 2); Als dritte Möglichkeit können Funktionen direkt in die Animation geschrieben werden. Dabei stehen innerhalb des Scriptes die Variablen "t"(momentaner Zeitpunkt in der Animation) und "dur"(Dauer der Gesamtanimation) zur Verfügung. Beispiel 3:: Gruppierung mittels ``sequence`` =============================================================================== Die in einem ````-Container enthaltenen Animationen werden nacheinander abgespielt. Wird keine absolute Dauer angegeben, entspricht die Dauer der Summe der Bruttozeiten aller Children:: Gruppierung mittels ``parallel`` =============================================================================== Container, dessen Children gleichzeitig abgespielt werden. Die Dauer entspricht der Dauer der längsten Child-Animation. Hat ein Child keine Dauer, wird die Dauer des Containers genutzt (in diesem Fall 3 Sekunden, da die längste Child-Animation drei Sekunden lang ist):: Attribute: keine. Animationselement ``tween`` =============================================================================== Veränderung einer Widget-Property über die Zeit:: Attribute: **property** Name der property, die auf dem Widget (bzw. dem als ``target`` angegebenen Widget) verändert werden soll. **type** (String) Datentyp für die ``from``, ``to``, ``by``-Angaben. Nicht jeder Datentyp kann sinnvoll getweent werden. Möglich sind beispielsweise: Integer, Number, Decimal, Point, Padding, Color, Shape. Es können nur Shapes getweent werden, die gleichartig sind (gleicher Typ / gleiche Anzahl Punkte etc.). **from** (Object, @, {...}) Ausgangswert des Tweens. **to** (Object, @, {...}) Endwert des Tweens. Animationselement ``switch`` =============================================================================== Veränderung einer Widget-Property in Form eines einfachen Umschaltens. Besonders geeignet für den Datentyp ``Boolean``. :: Attribute: siehe Tween. Ist beim Switch eine duration angegeben, so wird sie ignoriert. Ein Switch hat per Definition ``duration=0``. Animationselement ``animation`` =============================================================================== Dieser "Animationsbaustein" dient zur Integration von externen Elementen in eine Animation. Dies können Actions oder an anderer Stelle im Mad-Dokument notierte Animationen sein. Attribute: **reference** (Animation, @, {...}) Eine Animation, die an die Stelle des ``animation``-Tags in den aktuellen Kontext eingefügt wird. **action** (String, @, {...}) Eine Action. Als Werte können entweder ein Lookup auf eine im Mad definierte, benannte ```` oder ein Script übergeben werden. Nur wenn dieses Attribut genutzt wird, wirken sich die Attribute ``mode`` bzw. ``duration`` aus. **mode** (Symbol) Dieses Attribut wirkt sich nur aus, wenn mittels ``action`` eine Action in die Animation integriert wird. Wird der ``mode`` auf "once" gesetzt, wird die Action nur einmalig aufgerufen. "onceifdefined" bewirkt, dass die action einmalig aufgerufen wird, aber nur wenn sie definiert ist. Eine nicht definierte Action wirft keinen Fehler. Wenn dieses Attribut weggelassen wird, erfolgt der Aufruf der Action auf jedem Frame innerhalb der gesetzten Dauer. **duration** (Time, @, {...},INFINITE) Dieses Attribut wirkt sich nur aus, wenn mittels ``action`` eine Action in die Animation integriert wird. Dann bestimmt es die Zeit während der diese Action aufgerufen wird. Als Sonderfall gibt es den Wert "INFINITE". Dieser sorgt für ein endloses Laufen der Animation. Aufruf von Actions ----------------------------------- Wenn innerhalb einer Animation eine Action aufgerufen werden soll, kann dieses über das ``animation``-Tag erfolgen. Mittels des Attributes ``mode`` kann zwischen einem einmaligen Aufruf und einem wiederholten Aufruf unterschieden werden. Im folgenden Beispiel wird die Action "FrameAction" für die Dauer von 50 Sekunden bei jedem Frame aufgerufen:: // ... Mittels des Attribut ``mode`` kann ein einmaliges Aufrufen der Action bewirkt werden. Wenn dieses Attribut weggelassen wird, erfolgt der Aufruf der Action auf jedem Frame innerhalb der gesetzten Dauer. Sofern eine Duration für ein ``animation``-Tag angegeben ist, welches mittels ``mode`` auf einmalige Ausführunge geschaltet ist, wird die Duration als Wartezeit nach der Ausführung interpretiert. .. note:: Bei einer einzelnen Anweisung ist die Angabe duration="0" notwendig, damit sie ausgeführt wird. Wenn das ``animation``-Tag bspw. in eine ``sequence`` integriert ist, ist dieses nicht notwendig. // geht // geht nicht siehe Bug #281. Einmaliger Aufruf einer Action in einer Sequence:: <.../> <.../> // ... Beispiel einer endlos laufenden Frameanimation:: // ... **Übergabewerte an die aufgerufene Action:** Die Deklaration der Action soll zwei Argumente vorsehen:: ... wobei in ``widgetref`` das aktuelle Target-Widget, in ``val`` der aktuelle Animationswert zwischen 0 und 1 übergeben wird. Die Action kann dann ``val`` nutzen, um beliebige Manipulationen am Target-Widget vorzunehmen. Für Inlinescripte "{...}" kann auf die Argumente unter diesen Namen zugegriffen werden. Verweis auf andere Animationen ----------------------------------- Erlaubt die Angabe einer Animation (Tween, Sequence, etc.), die an die Stelle des ``animation``-Tags in den aktuellen Kontext eingefügt wird:: this.AnimationControl = "play"; // Verweis auf eine Animation welche in der Presentation definiert ist // eingebundene Animation Animationselement ``wait`` =========================== Mittels des ``wait`` Containers kann eine Pause in laufende Animationen eingebaut werden:: Im folgenden Beispiel wird zunächst die ``Location`` animiert, dann wird 5 Sekunden gewartet und anschließend wird das ``Shape`` animiert:: Animationselement ``iterator`` =============================================================================== Ein Iterator stellt innerhalb einer Animation eine Liste von Werten zur Verfügung die bei jedem Animationsdurchlauf auf das nächste Element weitergeschaltet wird. Attribute: **items** (List, @, {...}) Eine Liste der im Iterator enthaltenen Werte. Im folgenden Beispiel wird nach Klick auf ``widget1`` eine Animation gestartet, die sowohl ``loopitems`` als auch einen ```` nutzt. Als "Loopitems" der Animation sind die Childwidgets von ``widget2`` angegeben. Damit wird festgelegt, dass die Animation zweimal loopt (da ``widget2`` zwei Children hat); der Zugriff auf die einzelnen loopitems erfolgt über das ``target="item"``. Innerhalb der Animation ist ein ```` definiert, der über die Children von ``widget3`` iteriert. Der Zugriff auf diese Referenzen erfolgt über den Iterator-Namen (hier ``myIterator``). Das folgende Beispiel führt nacheinander folgende Aktionen aus:: widget2.child1 > Shapeanimation widget3.child1 > Visible widget2.child2 > Shapeanimation widget3.child2 > Visible ``widget3.child3`` wird nicht verändert. Beispiel:: this.AnimationControl = "play"; red green red green green Animationsspezifische Widget-Properties =============================================================================== **AnimationControl** (Symbol) Erlaubt die Steuerung der auf dem Widget definierten Animation(en). Werte: ``"play"``, ``"pause"``, ``"stop"`` JavaScript-Syntax =============================================================================== Die Animation des aktuellen Widgets abspielen:: this.AnimationControl = "play"; Eine benannte Animation abspielen: ``Animationreference.play(target);`` Im folgenden Beispiel wird das aktuelle Widget (``this``) von der Animation ``this.moveIt`` bewegt:: this.moveIt.play(this); Um eine Animation auf einem anderen Widget auszuführen, wird dieses Widget als ``target`` im ``play``-Aufruf der Animation übergeben:: // Lookup auf das Zielwidget var wgt = $(this,"widget2"); // Aufruf der Animation mit der in 'wgt' abgelegten Referenz auf "widget2" this.scaleIt.play(wgt); Zeitverhalten von Animationen =============================================================================== Die Gesamtdauer einer Animation setzt sich wie folgt zusammen:: (delay + (duration * loopcount) + (gap * (loopcount-1))) Die Dauer von Animationen kann von "außen" (Parent-Animation) oder von innen (Child-Animation) bestimmt werden. Ist auf einer "äußeren" Animation eine ``duration`` angegeben, welche zu kurz ist um die enthaltenen Animationen abzuspielen, wird die Animation bis zum Ende der "äußeren" ``duration`` abgespielt. Die evt. noch nicht abgespielten "inneren" Animationen werden verworfen. Sofern die "äußere" ``duration`` länger ist, als die enthaltenen Animationen, läuft die Animation einfach weiter, ohne dass Auswirkungen sichtbar werden. Beispiele zur Illustration des Zeitverhalten:: // Animationsdauer: // sequence undefiniert => parallel undefiniert => längster tween b: 2s // => parallel 2s + tween c 1s => sequence ist 3 Sekunden lang // Tween a ist bereits nach 1s zu Ende. // Animationsdauer: // sequence 5s - tween 1s => parallel 4s => tweens a,b sind 4 Sekunden lang // Animationsdauer: // sequence undefiniert => parallel undefiniert => a,b undefiniert // => c undefiniert => oberstes undefiniertes Element: Sequence // => sequence 1s (Default) => parallel 0.5s ==> a,b 0.5s // => c 0.5s // Animationsdauer: // sequence undefiniert => parallel undefiniert => a,b undefiniert // => c 1s => oberstes undefiniertes Element: parallel // => parallel 1s (Default) ==> a,b 1s // => sequence 2s // Animationsdauer: 12s, dabei sind die enthaltenen Animationen nach 8s fertig // Animationsdauer: 4s, der zweite Tween wird nicht mehr ausgeführt. Beispiele =============================================================================== Ein einfaches Beispiel mit ``delay``:: // der zweite Tween wird mit einer Verzögerung von 3 Sekunden gestartet this.AnimationControl = "play"; Mittels ``gap`` wird eine definierte Pause zwischen den mit ``loop`` definierten Wiederholungen eingesetzt:: this.AnimationControl = "play"; Ein umfangreicheres Beispiel erstellt eine Bilder-Slideshow mit dem Ken-Burns-Effekt (http://en.wikipedia.org/wiki/Ken_Burns_effect):: $(this,"showAnim").play(this); Das komplette MAD-Dokument zum :download:`Download <../reference/animation/kenburns.mad>`. .. _ref-charts-animation: Besonderheiten bei Chartanimationen ============================================== Chartanimationen nutzen die hier beschriebenen Animationsfeatures und Sprachkonstrukte. Allerdings werden einige zusätzliche Verfahren benutzt, um sehr granular auf die Einzelelemente von Charts (Balken, Linien, Labels, etc.) zuzugreifen. Das folgende Beispiel ist in einem PieChart definiert:: 1 2 3 4 5 7 9 10 12 13 14 Das Attribut ``loopitems`` wird in Zeile 2 mit dem Lookup auf ``@AnimationElements`` initialisiert. Damit stehen die "Hauptelemente" jedes Charts (hier: die Kreissegmente, in den anderen Charttypen die Balken, Säulen und Linien) in der Animation zur Verfügung, und die Anzahl der Wiederholungen der ``sequence`` ist auf die Anzahl der ``AnimationElements`` festgelegt. In Zeile 5 wird mit ``target="item"`` auf das jeweilige Loopitem zugegriffen. In diesem Fall wird die (Winkel-)Größe des Kreissegments von unsichtbar auf den vollen darzustellenden Wert animiert (Tween der Property ``Progress`` von 0 bis 1). ** heißt die nicht AnimationProgress??? ** Interessant ist auch das Timing diese Animation: hier werden die darzustellenden Werte für das Timing benutzt, so dass ein kleiner Wert (= ein kleines Kreissegment) weniger Zeit erhält als ein großer: ``reldur="@Values[*][0]"``. Dieser Zugriff auf Values ergibt eine Liste, z.B. ``[32,23,12,10]``. Für eine Animation, bei der jedes AnimationElement unabhängig vom Wert dieselbe Animationszeit erhält, kann ``reldur`` eine Liste ``[1,1,1,1,1,1,1,1]`` zugewiesen werden, die mindestens so lang sein sollte wie die Maximalzahl der erwarteten Werte. Mit jeweils einem ``iterator`` werden weitere Elemente der Chartdarstellung gesteuert (Zeile 3 und 4). In diesem Fall sind in einem Container Labels zwei Labelbars definiert, deren Children per ``iterator`` in der Animation zur Verfügung gestellt werden. Mit ``target="it"`` (dem Namen des ersten Iterators) kann sodann auf die Children von ``@Labels.ValueLabels``, mit ``target="it2"`` entsprechend auf die Children von ``@Labels.DiffLabels`` zugegriffen werden. Mit jedem Durchlauf der in Zeile 2 definierten Sequence wird ein darin definierter ``iterator`` ein Element weitergeschaltet. In Zeile 5 und 7 wird so den einzelnen Labels ein anderes Textformat zugewiesen. Selbstverständlich können weitere Animationselemente (wie die ``wait``-Anweisungen in Zeile 9 und 12) die Chartanmation vervollständigen. Die beiden Anweisungen bewirken, dass zwischem dem Umschlaten der beiden Labels eine kurze Pause ist (Zeile 9), und am Ende der Gesamtsequenz für einen Balken (Balken und zwei Labels verändert) eine etwas längere Pause (Zeile 12). Werden die Labels - wie im BarChart - direkt im Chart definiert, so ist auch ein Zugriff über die Chartproperty ``BarLabels`` möglich:: ``target="item.BarLabels[2]"`` schaltet hier das ValueLabel (index 2 der Liste BarLabels), ``target="item.BarLabels[3]"`` entsprechend das DiffLabel. *und das LineChart?*