May 12, 2014

Animating with Framer.js

Well, shit. Framer 3.0 released on May 13, and with that, this post became much less useful. It had maybe a good 12 hours of relevance, which I guess is better than nothing. If you want to learn more about animating with Framer, check out the revamped example library on the Framer.js site.

Making things move

You can animate almost any property of a Framer view—position (x/y coordinates), opacity, scale, width, height—and you can animate multiple properties at once. Every view has an animate() shortcut, which is the easiest way to get things moving.

See the Pen The Most Basic Framer.js Animation by Jay Stakelon (@stakes) on CodePen.

A default Framer.js animation

At minimum, you’ll need to declare the properties you want to animate. Even though it’s optional, you’ll also want to specify an animation curve (more on that in a second) and you also might want to specify the time the animation lasts in milliseconds.

myView.animate({
  properties: {
    x: 400,
    y: 500
  },
  curve: 'ease-in',
  time: 500
})

You can also create animation objects explicitly with new Animation() which allows you to trigger callbacks when they start and end. Check out the Framer docs if you’re interested in seeing how this works.

Basic easing curves

Framer.js gives us a couple ways to dial in animations using curves. An animation curve is an equation that defines how fast or slow an object animates over time. With curves, you can make animations feel natural or exaggerated. Take another look at the default animation above: there’s nothing in real life that actually moves like that. Objects slow down and objects bounce. Easing curves help our animations and interactions start to feel “real” to the user.

Framer gives us a couple of super-easy ways to tweak our animations with four built-in easing curves.

"linear" is the default curve where the object moves at a steady speed throughout the animation. "ease-in" starts slower at the beginning of the animation and speeds the object up gradually. "ease-out" starts at a higher rate and slows down at the end of the animation. And "ease-in-out" slows down at both the beginning and the end of the animation.

See the Pen Framer.js Easing by Jay Stakelon (@stakes) on CodePen.

Bezier curves

So, for real, there is absolutely nothing I can write here that will do a better job of explaining how cubic bezier curves work than www.cubic-bezier.com already does. If you’re interested in understanding how bezier animation curves work, just take two minutes and play around with it.

Bezier curves are infinitely flexible, but personally I’ve only used these in two situations. You can create an exaggerated version of a standard easing function—for example, a really aggro version of "ease-in-out" looks like "bezier-curve(.9,0,.1,1)". I’ve also used "bezier-curve(.5,-0.5,.5,1.5)" when I want an object to overshoot its target a bit on both ends of the animation (old Flash heads who remember “easeInOutBack”: this is it).

See the Pen Framer.js Bezier Curves by Jay Stakelon (@stakes) on CodePen.

Springs

This is my shit. I love Framer’s spring method for expressive and fine-tuned animations. It’s a little abstract but once you have a general idea of what the parameters do it’s a lot of fun to tweak and play with. This demo shows a pretty awesome range of what you can do with springs (found on Designer News).

Start by imagining that the object you’re animating is attached to an actual spring. The method takes three arguments, which I’ve always understood best to stand in for physical properties:

  • tension – how tightly that spring is coiled
  • friction – how much effort it takes to move the object
  • velocity – the initial speed that launches the object

One important thing about timing: using the spring() curve type overrides any time value that you specify for the animation. You’ll see in the below examples how different combinations of values end up creating animations of different lengths.

Tension

The Framer docs describe this as “the stiffness of the spring”. As you increase the tension value, you get more speed and more bounce. Lower values accelerate more gradually and have a looser bounce at the end. Higher values accelerate rapidly and bounce quicker and faster at the end.

See the Pen Framer.js Springs – Tension by Jay Stakelon (@stakes) on CodePen.

Friction

I think of friction like the brake on a bicycle. The higher the value, the tighter the brake and the more resistance that’s continually applied to the object. Dial up the friction to see things slow down a little and the spring itself dampen a lot.

See the Pen Framer.js Springs – Friction by Jay Stakelon (@stakes) on CodePen.

Velocity

Out of the three spring parameters, this one has been the toughest for me to wrap my head around. It’s the initial velocity of the object, which I think of as giving the object a little extra push. It makes sense that higher values tend to exaggerate the distance that the object bounces at the end of its trajectory.

See the Pen Framer.js Springs – Velocity by Jay Stakelon (@stakes) on CodePen.

Bringing it all together

Let’s revisit the example prototype from my Getting Started With Framer tutorial. We were building a Tinder knockoff called The Hollerator, and we had gotten far enough to animate a slide-out “hamburger” menu. Here are an updated set of example files if you want to follow along with this quick animation polish session.

We had started by just animating the x property of the Main view, to slide it over to the side and expose the menu:

Main.animate({
  properties: {x: 540}
})

That looked like this, which is way too basic for an app of The Hollerator’s caliber.

default-anim

Since the easiest way to start dialing in an animation is to experiment with a built-in easing curve, I might try "ease-out" which’ll slow the animation down at the end.

Main.animate({
  properties: {x: 540},
  curve: 'ease-out',
  time: 300
})

But to give the navigation animation a little more snap and bounce, let’s use a spring. Since springs override the time property, we can just remove it.

Main.animate({
  properties: {x: 540},
  curve: 'spring(400,30,500)'
})

spring-anim-01

Much better, but if you look closely at the navigation closing you’ll see that it bounces a little too hard in that direction, revealing a bit of empty space on the right. So let’s adjust the parameters a bit on the animation that hides the nav, increasing the friction value just enough to dampen that bounce.

// show navigation
curve: 'spring(400,30,500)'
// hide navigation
curve: 'spring(400,38,500)'

spring-anim-02

Resources

Obviously the Framer docs are the place to start, and specifically the source from the Animation lesson (which I very liberally borrowed for all of the examples on this page).

If you’re interested in learning more about animation curves in general, this page from the docs of an animation library called Tweener has a great visualization of different animation curves. Take that over to cubic-bezier.com for an interactive crash course in animation curves.