Easing Functions

October 10, 2021

An easing function f(x)f(x) is a mathematical function such that f(0)=0,f(1)=1f(0)=0, f(1)=1 that precisely describes the rate at which something moves between two states during animation.

🔗Types of Easing Functions

🔗Linear Function

There's only one linear easing function f(x)=xf(x)=x because it's constrained at two points:

🔗Quadratic Functions

Quadratic easing functions can have exactly one critical point (a point on the function such that f(x)=0f'(x)=0). A common choice is to place that point at x=0x=0 or x=1x=1.

f(x)=x2f(x)=x^2 (ease-in):
f(x)=1(1x)2f(x)=1-(1-x)^2 (ease-out):

🔗Cubic Functions

Cubic easing functions can have up to two critical points. When they are placed at x=0x=0 and x=1x=1 respectively, the result is a well-known kind of sigmoid function called a smoothstep function. It's used so frequently that the OpenGL Shader Language provides a built-in function for this.

f(x)=x2(32x)f(x)=x^2(3-2x) (the good old smoothstep function):

One might notice that the deceleration rate ( f(x)f''(x)) peaks at the end, which is a little bit unnatural because, when it's thought of as a kinetic motion, it doesn't quite align with Coulomb's friction model. For this reason, one could say that the CSS ease-in-out function with a f(x)f''(x) profile containing two plateaux would give a more natural feel, although the difference is subtle at best, and there's a huge difference in the computational overhead.

🔗Step Functions

The precise definition of step easing functions varies between contexts. Here we use the round function, which evaluates to the nearest integer of a given real number (with an arbitrary tie-breaking).

f(x)=round(x)f(x)=round(x):
f(x)=round(4x)/4f(x)=round(4 x)/4:
f(x)=round(12x)/12f(x)=round(12 x)/12:

🔗Elastic Easing

This class of easing functions can be derived as an approximation of a second-order linear ordinary differential equation's solution.

We start with the following differential equation, where cc is the dampening factor and kk is the spring constant:

f(x)+cf(x)+k(f(x)1)=0f''(x) + cf'(x) + k(f(x) - 1) = 0

Assuming cc is sufficiently small, the general solution is:

f(x)=1+ewx{Asin(ωx)+Bcos(ωx)}f(x) = 1+e^{-wx} \left\{A\sin(\omega x)+B\cos(\omega x)\right\}

This is inconvenient to use as an easing function because it never completely settles. To work around this problem, we substitute ewxe^{-wx} with (1x)2(1-x)^2, which is similarly monotonically-decreasing and convex in the range [0,1][0, 1]. After applying the easing function conditions, we arrive at the following function:

fA(x)=1(1x)2(2sin(ωx)ω+cos(ωx))f_A(x)=1-\left(1-x\right)^2 \left( \frac{2\sin(\omega x)}{\omega} + \cos(\omega x) \right)ω0\omega \to 0 converges to the smoothstep function:
ω=10\omega = 10:
ω=20\omega = 20:

🔗Cubic Bézier Curves

Bézier curves are parametric curves that are most commonly used in vector graphics. Turns out, they are also excellent as easing functions owning to their expressiveness and ease of control.

A cubic Bézier curve is formed by two endpoints and two control points. For easing functions, the endpoints are usually [(0,0),(1,1)][(0, 0), (1, 1)] (other choices are possible but not really useful). The control points determine the curve's tangents and curvatures at their respective endpoints.

Evaluating a cubic Bézier timing function—finding yy for a given xx—requires finding the real roots of a cubic equation. This is done through an analytic method such as Cardano's algorithm or an iterative method such as Newton's method. Modern web browsers use the combination of Newton's method and the bisection method for fallback (Gecko, Blink, Servo).

[(0,0),(0.25,0.1),(0.25,1),(1,1)][(0, 0), (0.25, 0.1), (0.25, 1), (1, 1)] (the CSS ease timing function):
[(0,0),(0.42,0),(0.58,1),(1,1)][(0, 0), (0.42, 0), (0.58, 1), (1, 1)] (the CSS ease-in-out timing function):

If any of the X values are outside the range [0,1][0, 1] (which is disallowed in CSS Easing Functions Level 1), the resulting cubic Bézier easing function may be multi-valued: