Animation basics
Time to animate!
A simple animation
Let’s recreate the circle and give it a descriptive name:
orangeCircle = new Layer
width: 300
height: 300
backgroundColor: "orange"
borderRadius: 150
The x
and y
properties were omitted because we will now use functions to position the circle.
Like this:
orangeCircle = new Layer
width: 300, height: 300
backgroundColor: "orange"
borderRadius: 150
x: Align.center
y: Align.center
The Align.center
function looks at the width (or height) of the screen and calculates which x
or y
value is needed to place the layer in the center.
You can test this by changing the preview window to one of the device presets. Whatever the dimensions of the screen might be, the circle will always be smack in the middle.
We now add an animation in the simplest way possible.
Right-click orangeCircle
in the Layer Panel to add an Animation.
Give it zero opacity (with the slider in the Properties Panel), and a scale of 6
(you’ll have to type the value in the Properties Panel).
orangeCircle.animate
opacity: 0.00
scale: 6.00
options:
time: 1
curve: Bezier.ease
Creating an animation is simple: after animate
you type the properties to which you want to animate.
opacity: 0
– animate to zero opacityscale: 6
– make the circle six times as big
Here we’re animating opacity
from 1
(the default, fully opaque) to 0
(completely transparent) and scale
from 1
to 6
, all at the same time. You can add as many properties as you want and they will all animate simultaneously.
Framer also added the default animation options
. These values refer to the animation itself:
time: 1
– the animation will take one second to completecurve: Bezier.ease
– this default curve makes an animation look more natural because it doesn’t start abruptly and slows down gradually at the end
Let’s add a few more properties: delay
and repeat
.
orangeCircle.animate
opacity: 0.00
scale: 6.00
options:
time: 1
curve: Bezier.ease
repeat: 5
delay: 1
You can also find these settings in the animation tab of the Properties Panel. Click the handle next to the animation to put it back in edit mode.
repeat: 5
– repeat the animation five times (after the default first run)delay: 1
– with a delay of one second (between each repetition)
How to restart the animation? You can, of course, ⌘R reload the prototype, but wouldn’t it be better if we could trigger it with a tap?
An animation triggered by a tap
Taps, swipes and other gestures are called events in Framer. You make a layer listen for an event, so it knows what to do when it’s tapped or dragged, etc.
You can add (most) events with the Event button, or by right-clicking the layer’s name in the Layer Panel.
Right-click orangeCircle
in the Layer Panel to give it a Tap
(or Click
) event.
orangeCircle.onTap (event, layer) ->
In this event handler, you then write what should happen when this layer is tapped, this can be just one animation (or other action), or many. Be sure to indent, so that the lines are inside the event handler’s block.
What do we want to happen when the user taps it? We want to trigger our animation, so we place the animate
block inside the event block.
orangeCircle.onTap (event, layer) ->
orangeCircle.animate
opacity: 0.00
scale: 6.00
options:
repeat: 1
Pro tip: To shift the indentation of multiple lines (e.g., the animation above) to the right: select the lines and type ⌘]. (To the left: ⌘[)
I got rid of the delay and changed the repeat
to just 1
so that it animates twice. I also removed the time
and curve
properties because they contained the default values anyway.
We’ve attached an onTap
event to the layer. The above lines say the following:
In the event of a tap on orangeCircle, run this animation on orangeCircle.
The (event, layer)
parameters show that the event handler receives information about the ‘event’ itself, and the ‘layer’ that’s being tapped.
Since we want to animate the layer that’s tapped (and not any another layer), we can write layer.animate
instead of orangeCircle.animate
.
orangeCircle.onTap (event, layer) ->
layer.animate
opacity: 0.00
scale: 6.00
options:
repeat: 1
Using an animation object
When you want to have more control over your animations, like being able to stop them, reverse them, or chain animations, you can use ‘animation objects.’
We’ll create one now. Type this under the code that created the layer:
# grow the circle
circleGrow = new Animation orangeCircle,
opacity: 0
scale: 6
options:
curve: Spring
You create an Animation
object with the new
keyword, just like a layer object. And right after Animation
, you set which layer it should animate (here orangeCircle
), followed by a comma (,
).
I added a spring curve
so that we’ll have a bouncy animation.
In our ‘event handler,’ we can now remove the earlier layer.animate
code and simply start()
our animation object.
# grow the circle
circleGrow = new Animation orangeCircle,
opacity: 0
scale: 6
options:
curve: Spring
orangeCircle.onTap (event, layer) ->
circleGrow.start()
Note that text that starts with a hash, like # grow the circle
, is ignored by Framer. You can use hashes to leave comments for yourself or temporarily cancel out a few lines of code.
There’s a keyboard shortcut for commenting out text: ⌘/. You don’t have to drag and select the text for it; the cursor just needs to be on the line you want to comment out.
You’ll notice that you still have to reload the prototype to reset the animation. Animations only go one way, so we need a second animation to shrink the circle again.
Fortunately, there’s a function to quickly create the reverse of an existing animation object:
# shrink it again
circleShrink = circleGrow.reverse()
We made a new animation, circleShrink
, by calling the reverse()
function on circleGrow
. This new animation does exactly the same thing as the original one, but backwards.
Next, we want to know when the growing ends so that we can trigger the shrinking. We’ll listen to the onAnimationEnd
event of the circleGrow
animation. The Event button (or right-clicking the layer name) only lets you add events to layers, but you can add the event to orangeCircle
and then change it to circleGrow
.
# trigger shrinking after growing
circleGrow.onAnimationEnd (event, layer) ->
circleShrink.start()
These new lines say:
In the event of the ending of the circleGrow animation, start the circleShrink animation.
If you’re adding just one single function to an event you can also write it more concisely, like this:
# trigger shrinking after growing
circleGrow.onAnimationEnd circleShrink.start
(Note that the parenthesis after start()
are omitted.)
Now, what do you think would happen if you added this extra line?
circleShrink.onAnimationEnd circleGrow.start
Try it.