Intro to Framer » Animation basics

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
Download Framer project

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
Download Framer project

Creating an animation is simple: after animate you type the properties to which you want to animate.

  • opacity: 0 – animate to zero opacity
  • scale: 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.

An orange circle growing while fading out

Framer also added the default animation options. These values refer to the animation itself:

  • time: 1 – the animation will take one second to complete
  • curve: 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
Download Framer project

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)
A pulsating orange circle

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
Download Framer project

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.

An animation triggered by a tap

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
Download Framer project

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()
Download Framer project

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.

The animation object gets triggered by a tap

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()
Download Framer project

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()
Download Framer project

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.

An animation and its reverse