15. Animations
Animations are created using the Animation component.
To add animation to a primitive, we simply add an animation
attribute and configure it with the animation properties. (As we have seen, properties are name: value;
pairs):
<a-box position="0 1.6 -2" animation="property: rotation; to: 0 360 180; dur: 5000; loop: 2">
Don't be confused with the fact that one of the properties we need to configure for the animation is called… property
.
The main properties are:
property: the attribute to animate. In the example, we are animating the rotation of the box.
to: the target value for the attribute. In the example, we want to animate the rotation of the box from it's default value "0 0 0" to the target value of "0 360 180".
dur: the duration of the animation, or how long it will take to go from the initial value to the target value. In the example, we want to make the animation take 5 seconds (5000 milliseconds) to animate from "0 0 0" to "0 360 180".
loop: how many times we want to repeat the animation. We can specify a number like in the example to make the animation run twice, or specify
true
to create a never ending animation.
Easings
Easings defined how the animation progresses through time: does it have a constant speed?, or does it start slow but gains speed as it progresses?
There are many types of easing functions. Example 1200-animations-02-easings
shows only a few. The main categories of easings are:
linear: constant speed (the bottom box in the example).
easeIn: the animation starts slow and gains speed as it progresses (top box).
easeOut: the animation starts fast but loses speed as it progresses (second box from the top).
easeInOut: the animation starts slow, gains speed, and then loses speed as it reaches the end (third box from the top)
The easesomething category uses speficic functions for the variation of speed (the example illustrates only the Quad function). The animation component documentation lists other possibilities for easing: https://aframe.io/docs/1.0.0/components/animation.html#easings
To set the easing function to use in an animation we specify the easing
property:
<a-box scale="0.5 0.5 0.5" position="-3 0 -4"
animation="property: position; dur: 5000; easing: linear; to: 3 0 -4; loop: true" >
</a-box>
Analyse the source code of the following example and watch it run. Although it is hard to see, the boxes actually all take the same amount of time to reach their final position – 5 seconds.
Go to the A-Frame page that documents the Animation component and try out different easing functions in example 1200-animations-02-easings
Chaining animations
We can give the impression of chained animations (i.e., sequential animations in different objects) by carefully setting the duration
and delay
of each animation. The delay
property tells A-Frame how long it should wait before starting the animation. In example 1200-animations-03-chaining
we have three animated boxes:
The animation of box #1 starts immediately (no delay) and lasts for 1 second.
The animation of box #2 starts with a delay of 1 second (so it starts when the animation of box #1 ends) and lasts for 1 second.
The animation of box #3 starts with a delay of 2 seconds (so it starts when the animation of box #2 ends) and lasts for 1 seconds.
<a-box
position="-1 1.6 -2"
scale="0.5 0.5 0.5"
color="#ff0000"
animation="property: height; from: 1; to: 2; dur: 1000; delay: 0"
>
</a-box>
<a-box
id="sec"
position="0 1.6 -2"
scale="0.5 0.5 0.5"
color="#00ff00"
animation="property: height; from: 1; to: 2; dur: 1000; delay: 1000"
>
</a-box>
<a-box
id="thi"
position="1 1.6 -2"
scale="0.5 0.5 0.5"
color="#0000ff"
animation="property: height; from: 1; to: 2; dur: 1000; delay: 2000"
>
</a-box>
Rotation and scale axis
You have noticed that in previous animations, the boxes grow and rotate from their center. This is because the reference point for most entities in A-Frame is the center of the object. What if we want to rotate a box not around the center but from another arbitrary point?
For this we need to nest our object inside another entity and apply the animation to the outer entity. We then displace the inner object, displacing the reference point:
<a-entity
id="rotatingbox"
position="0 2 -2"
animation="property: rotation; from: 0 0 0; to: 0 0 360; dur: 1000; loop: true; easing: linear"
>
<a-box
position="0 0.25 0"
width="0.1"
height="0.5"
depth="0.1"
color="#ff0000"
>
</a-box>
</a-entity>
<a-entity
id="rotatingsphere"
position="0 0 0"
animation="property: rotation; from: 0 0 0; to: 0 360 0; dur: 5000; loop: true; easing: linear"
>
<a-sphere position="0 0 -5" radius="0.1" color="#00ff00"> </a-sphere>
</a-entity>
We can do the same for scaling objects:
Animating multiple properties
We can animate multiple properties on the same entity by adding multiple Animation components to that entity. In order to do that, we need to change the name of the animation
attribute because we cannot have the same attribute name duplicated in an HTML element. A-Frame does this by allowing us to append a suffix to the attribute name for the component. The suffic must come after a double underscore __
as in the following code:
<a-box
position="-1 1.6 -2"
scale="0.5 0.5 0.5"
color="#ff0000"
animation__height="property: height; from: 1; to: 2; dur: 1000; loop: 1"
animation__rotation="property: rotation; from: 0 0 0; to: 360 0 0; dur: 1000; loop: true"
animation__color="property: color; from: #ff0000; to: #0000ff; dur: 1000; loop: true; dir: alternate"
>
Notice how we are addding 3 animations. Each animation is defined by the animation
attribute with a different suffix __height
, __rotation
, and __color
. I advice you to use suffix names that are meaningful – in my example, the suffix corresponds to the property that is being animated. This is not mandatory, though.
Also note that each animation is completely independent from the others. The __height
animation only runs once (loop: 1
). The __rotation
and __color
animations run forever (loop: true
).
Also note that we can animate colors too! However, in order for colors to be animatable, you need to use the #rrggbb
format.
The __color
animation in example 200-animations-04-multiple
uses the dir
property. Check the documentation for what it does…
Interactive animations
We can also make animations interactive by defining which events trigger an animation.
For example, if we want to start animating a box only when the cursor is over that box, we can define the startEvents
property to mouseenter
:
<a-box
position="-1 1.6 -3"
color="#ff0000"
animation="property: height; dur: 2000; from: 1; to: 2; startEvents: mouseenter"
>
</a-box>
Or to click
even:
<a-box
position="1 1.6 -3"
color="#ffff00"
animation="property: height; dur: 2000; from: 1; to: 2; startEvents: click"
>
</a-box>
We can even make the animation pause depending on interaction events by defining also the pauseEvents
property:
<a-box
position="-1 1.6 -3"
color="#ff0000"
animation="property: height; dur: 2000; from: 1; to: 2; startEvents: click; pauseEvents: mouseleave"
>
</a-box>
In the previous box, the animation starts when the box is clicked, and paused when the cursor leaves the box.
A-Frame Animations also has a resumeEvents
property, but it does not seem to work correctly…
Exercises
Animations-01
Create an animation like in the following example. A series of six boxes stacked on each other. The bottom box is 5x5x0.25 meters, the next box 4x4x0.25 meters, 3x3x0.25, 2x2x0.25, 1x1x0.25, and the top box is 0.5x0.5x0.25. Boxes rotate indefinitely. The bottom box takes 5 seconds to complete one rotation and the next box takes 4 seconds, and so on…
Animations-02
Try to recreate the animation in the following example. Note that the arm rotates around the shoulder point.
References
- Animation component
- Documentation: https://aframe.io/docs/1.0.0/components/animation.html