Animation

Version 3 (coder, 17/06/2015 23:33)

1 1 admin
h1. Animation
2 1 admin
3 1 admin
{{>toc}} 
4 1 admin
5 1 admin
libavg contains a powerful animation framework that allows you to quickly author time and event-based changes in nodes. Animations can change the values of all numeric node attributes. They can be combined to execute in parallel or in series, they can switch states when some external event occurs, and callbacks can be registered that are called when animations start or stop.
6 1 admin
7 1 admin
h1. Linear Animations
8 1 admin
9 1 admin
It is very simple to animate node attributes:
10 1 admin
11 1 admin
_anim1.py_
12 1 admin
13 1 admin
<pre><code class="python">
14 1 admin
#!/usr/bin/env python
15 1 admin
# -*- coding: utf-8 -*-
16 1 admin
17 1 admin
from libavg import *
18 1 admin
19 1 admin
def startAnim():
20 1 admin
    animObj.start()
21 1 admin
22 1 admin
player = avg.Player.get()
23 1 admin
canvas = player.createMainCanvas(size=(640,480))
24 1 admin
rootNode = canvas.getRootNode()
25 1 admin
node = avg.WordsNode(pos=(10,10), font="arial",
26 1 admin
        text="Hello World", parent=rootNode)
27 1 admin
28 1 admin
animObj = LinearAnim(node, "x", 2000, 0, 200)
29 1 admin
player.setTimeout(0, startAnim)
30 1 admin
31 1 admin
player.play()
32 1 admin
</code></pre>
33 1 admin
34 3 coder
This creates an animation that moves the node from @x=0@ to @x=200@ over a course of 2000 milliseconds. The framework takes care of updating the position each frame. Point and color attributes (such as @pos@, @size@ and @fillcolor@) can be animated in the same way. @LinearAnim@ has a few additional optional parameters, which are described in detail in the [[reference]]. Using this class, you are independent of the framerate: if you change the framerate (maybe because you're running the code on a different computer with a different refresh rate), the animation will still take the same amount of time to complete. It'll just display more or less frames. There is another advantage: If something happens while the animation is running (the user presses a cancel button, for instance), you can just call @animObj.abort()@ and it'll stop dead in it's tracks. The animation framework also makes sure that only one animation per attribute is running at one time. If a second one is started, the first one is aborted.
35 1 admin
36 2 coder
There are convenience functions that handle fading the opacity of nodes called @fadeIn()@ and @fadeOut()@.
37 1 admin
38 3 coder
Interpolation of color values is done in the CIE L'ch color space for best results - see https://www.libavg.de/blog/colors/ for an explanation of why this is a good thing.
39 3 coder
40 1 admin
h1. Easein/out
41 1 admin
42 3 coder
@LinearAnim@ moves the attribute at a constant speed with no acceleration or deceleration. The @EaseInOutAnim@ class encapsulates an animation that proceeds in three phases: ease-in, linear and ease-out. Constructor parameters determine the length of each phase. Start and end speed are zero. Ease-in and ease-out phases have the shape of one quadrant of the sine curve. Less mathematically put: The animation will accelerate and decelerate at the beginning and end and look a lot smoother because of this.
43 1 admin
44 1 admin
h1. ParallelAnim
45 1 admin
46 2 coder
In many cases, you will want to start several animations at once. This can be accomplished using the @ParallelAnim@ class:
47 1 admin
48 1 admin
_anim2.py_
49 1 admin
50 1 admin
<pre><code class="python">
51 1 admin
#!/usr/bin/env python
52 1 admin
# -*- coding: utf-8 -*-
53 1 admin
54 1 admin
from libavg import *
55 1 admin
56 1 admin
def startAnim():
57 1 admin
    animObj.start()
58 1 admin
59 1 admin
canvas = player.createMainCanvas(size=(640,480))
60 1 admin
rootNode = canvas.getRootNode()
61 3 coder
node = avg.RectNode(pos=(10,10), size=(100,100), fillcolor="FF0000", fillopacity=1.0,
62 3 coder
        parent=rootNode)
63 1 admin
64 1 admin
animObj = ParallelAnim(
65 3 coder
    [LinearAnim(node, "pos", 2000, (0,0), (200,10)),
66 3 coder
     LinearAnim(node, "fillcolor", 2000, "00FFFF", "FF0000")])
67 1 admin
player.setTimeout(0, startAnim)
68 1 admin
69 1 admin
player.play()
70 1 admin
</code></pre>
71 1 admin
72 3 coder
The example code moves the node down and to the right over a course of 2 seconds while changing its color at the same time. Calling @abort()@ on a @ParallelAnim@ will stop all child animations. @ParallelAnim@ is sometimes useful on its own, but it's really powerful in combination with @StateAnim@.
73 1 admin
74 1 admin
h1. StateAnim
75 1 admin
76 1 admin
More complex animations can be scripted using @StateAnim@. Objects of this class contain a number of animations (so-called "states") that can be executed in an arbitrary sequence. At most one of these animations is active at once. The end of one animation can trigger the start of another one, and states can be set from a python script. A simple use for a @StateAnim@ is as a predetermined sequence of animations, but animations that take different routes depending on user input events are also possible. There is support for debugging animation states by calling @StateAnim.setDebug(True)@. This causes all state changes to be dumped to the console.
77 1 admin
78 2 coder
To make sure there are no discontinuities between two states, @Anim.start()@ has an optional parameter @keepAttr@. If this is set to True, the attribute is not changed at the beginning of the animation and the animation runs only for an appropriate part of the time that the duration parameter specifies. So, suppose that in @anim2.py@ above, @start(True)@ is called and @x=50@ before the animation starts. Since this is one-quarter into the range 0-200, the animation will run for 1500 ms (=2000*0.75) and the node will move from 50 to 200 in this time.
79 1 admin
80 1 admin
Note that changing the state of a @StateAnim@ during an animation callback is not supported. An attempt to do so is silently ignored.
81 1 admin
82 1 admin
h1. Other Animations
83 1 admin
84 1 admin
@WaitAnim@ does nothing for a predetermined amount of time. @ContinuonsAnim@ continually changes one attribute and doesn't stop by itself.