DEV Community

Cover image for Understanding the Bézier Curves 🙈
Wei Gao
Wei Gao

Posted on

Understanding the Bézier Curves 🙈

Photo: Foucault Pendulum at the Physics and Astronomy Building of University of Washington

Intuition

Omitting the construction details, a cubic Bézier curve is a [0,1] curve with at most two smooth turns.

With CSS, a cubic Bézier curve is defined by four points. The first point is (0,0), the last point is (1,1), and you need to supply only the second (x1, y1) and the third (x2, y2) points:

cubic-bezier(x1, y1, x2, y2) /* you drop the French accent mark, too */
Enter fullscreen mode Exit fullscreen mode

You can play around with the cubic Bézier curves at this website.

Intuitively, think of a cubic Bézier curve this way: You leave the origin (0, 0) towards the direction of the second point, and arrive at the terminal (1, 1) after bending towards the third point. I think of the smooth turn in the middle as the joint of the two forces.

Linear, Quadratic, and Cubic Bézier Curves

There are some interesting mathematical characteristics of Bézier curves.

If you glue two “free” points together, you get a lower degree Bézier curve — you make one fewer turn. So dropping one point from a cubic Bézier curve gives you a quadratic Bézier curve. And dropping yet another gives you the linear curve.

Here's cubic-bezier(.23, .86, .23, .86):

Joining the second and the third point of a cubic Bézier curve gives you a quadratic Bézier curve, one with only one turn

And cubic-bezier(0, 0, 1, 1):

While the standard CSS easing functions allow for cubic Bézier curves, they don’t necessarily go into that third order.

CSS's Animation Timing Functions

linear is the trivial, "first order" linear Bézier curve.

The ease-in and the ease-out are both quadratic. This can be seen by the numbers. The ease-out, cubic-bezier(0, 0, .58, 1) has the second point (remember you don’t need to define the first point, so 0, 0 define the second point) joined with the starting point. And the ease-in, cubic-bezier(.42, 0, 1, 1) has the third point joined with the end point. As you may as well easily seen in the graph, you make only one turn.

 raw `ease-in` endraw  and  raw `ease-out` endraw

A lot of physics can be expressed with the quadratic Bézier curves already. Item dropping, for example, is simply “easing-in”. I haven’t computed if the standard ease-in matches earth’s gravity or not — there should be a planet where it matches.

For a nice visualization of ease-in and ease-out, check out these material design’s illustrations. Please do take a look at the accelerate easing there. It speaks for the scene.

The ease and the ease-in-out are cubic. There are two turns in both these curves. Pendulums are “easing-in-out”. You move faster and faster towards the bottom, and slower and slower towards the two ends.

 raw `ease` endraw  and  raw `ease-in-out` endraw

One way to know when you need a cubic Bézier curve is when you find two forces. Throw an object into the sky. You apply an initial throwing force, this supplies the direction of your first intermediate point. At the same time, as gravity is constantly pulling your object towards the ground, the trajectory is going to bend towards the second intermediate, before stopping at your desired location, or hit the ground.

Now it should become really straightforward to create animations that look real. Think about what forces are applied. Visualize that with your Bézier curves, and apply to the translate.

Sometimes we simplify the reality a little bit, assuming the object was just given an initial speed. Like a message flies in from beneath and stops at your eyesight. It's blunt, there's no throwing. It just happened. Nothing spectacularly wrong with an ease-out, but I guess our subconscious will love the ease.

Practice

So I was trying to reverse engineer the animation in this design:

Pendulum

At first sight, it looks like an ease-in-out, like a pendulum. A frictionless pendulum swing is symmetrical. I should be able to create this with an infinitely looping reversing quadratic function. I can pick either way, going up or down, and reversing it gives the other direction.

@keyframes one-way-pendulum {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(1500px);
  }
}

.card {
  animation: one-way-pendulum 1s cubic-bezier(0.6, 0, 1, 1) infinite;
  animation-direction: alternate;
}
Enter fullscreen mode Exit fullscreen mode

It works! But wait, it's not pausing!

Pausing Pendulum

CSS animations' looping scheme does not offer a too obvious way to implement a pause between iterations. You would have to implement the gap by combining the loops. See this stackoverflow discussion.

This means that my animation would have to include both ways of the pendulum. Up and down. So a quadratic Bézier curve would not be enough. I really need the cubic one.

@keyframes pausing-pendulum {
  0%,
  20% {
    transform: translateY(0);
  }
  40%,
  50% {
    transform: translateY(1500px);
  }
  70%,
  100% {
    transform: translateY(0);
  }
}

.card {
  animation: pausing-pendulum 4s cubic-bezier(0.5, 0, 0.5, 1) infinite;
}

Enter fullscreen mode Exit fullscreen mode

Now it nicely pauses between iterations.

Which Bézier Curve Is Faster?

The three-card animation looks cool, one falling after one another. To me it looks like they're animating at the same time, but with a different gravity. The main card starts off slowest, the second card is a bit faster, while the third card the fastest. They come back with the same reversed speed, too.

So that first perpetuo should still work. All I need to do is to give the other cards a more drastic Bézier curve.

animation: pendulum 1s cubic-bezier(0.6, 0, 1, 1) infinite; /* the front most card */
animation: pendulum 1s cubic-bezier(0.3, 0, 1, 1) infinite; /* this one is faster */
animation: pendulum 1s cubic-bezier(0.1, 0, 1, 1) infinite; /* fastest of the three */
Enter fullscreen mode Exit fullscreen mode

Note that the .3 curve is faster than the .6 one. The .6 curves bends more drastically, it means it's slowing down faster.

Now we have those three perpetuo cards..

🐛🐛🐛

To replicate the pausing for the tri-cards, you just play with the numbers. EZPZ now 🐒. Note again that the less drastic curve has a faster initial dropped speed.


animation: pausing-pendulum 4s cubic-bezier(0.5, 0, 0.5, 1) infinite; /* main card */
animation: pausing-pendulum 4s cubic-bezier(0.5, 0.1, 0.5, 0.9) infinite; /*  faster */
animation: pausing-pendulum 4s cubic-bezier(0.5, 0.2, 0.5, 0.8) infinite; /*  fastest */
Enter fullscreen mode Exit fullscreen mode

CodePen Link

References

Top comments (8)

Collapse
 
one_too_cro profile image
Saurabh

Is it just on my end or are some of the images not showing?

Collapse
 
wgao19 profile image
Wei Gao

Which ones are not showing?

Collapse
 
one_too_cro profile image
Saurabh

See the sections titled "Pendulum" and "Pausing Pendulum". So I'm not really sure if there was supposed to be an image there (but I wondered because there's lots of white space).

Thread Thread
 
wgao19 profile image
Wei Gao

Do you see the CodePen examples under those sections? There should be four of them, each should be rendering the animations.

Thread Thread
 
one_too_cro profile image
Saurabh

I'm unable to see them on Firefox Quantum (64.0.2). But it works fine on Chrome. Possibly some parity issues in rendering or it might be one of my extensions. Thanks for your help!

Thread Thread
 
one_too_cro profile image
Saurabh

I don't know what happened, but now I am able to see it correctly even on FF.

Collapse
 
ahmedam55 profile image
Ahmed Mahmoud

Thanks for your time and effort! Really helpful!

Collapse
 
wgao19 profile image
Wei Gao

Really glad it's helped :) Thanks for letting me know!!