Animation Basics

Mastering Easing Functions

15 min read Beginner Interactive Demo

Why Linear Motion Feels "Off"

In the real world, things rarely start or stop instantly. Cars accelerate. Balls bounce. Doors swing shut with momentum. But by default, computers move things linearly — constant speed from A to B.

To make games feel natural and "juicy", we need Easing Functions. These are math formulas that distort time to create acceleration and deceleration.

Visualizing Easing

Select different easing functions below to see how they affect a ball's movement. The graph shows position over time.

Position vs Time
Result

The Magic Formula

All easing functions take a standard form: they accept a value t (time) between 0 and 1, and return a modified value.

easing-functions.js
const Easing = {
    // Linear: No change
    linear: t => t,

    // Ease In: Starts slow, speeds up (t²)
    easeInQuad: t => t * t,

    // Ease Out: Starts fast, slows down
    easeOutQuad: t => t * (2 - t),

    // Ease In Out: Slow start, fast middle, slow end
    easeInOutQuad: t => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
    
    // Elastic: Overshoots and snaps back
    easeOutElastic: t => {
        const c4 = (2 * Math.PI) / 3;
        return t === 0 ? 0 : t === 1 ? 1 :
            Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
    },
    
    // Bounce: Bouncing ball effect
    easeOutBounce: t => {
        const n1 = 7.5625;
        const d1 = 2.75;
        if (t < 1 / d1) {
            return n1 * t * t;
        } else if (t < 2 / d1) {
            return n1 * (t -= 1.5 / d1) * t + 0.75;
        } else if (t < 2.5 / d1) {
            return n1 * (t -= 2.25 / d1) * t + 0.9375;
        } else {
            return n1 * (t -= 2.625 / d1) * t + 0.984375;
        }
    }
};

How to Use It

To use easing, you need to track the progress of your animation manually.

  1. Track currentTime and duration.
  2. Calculate normalized time t = currentTime / duration (0 to 1).
  3. Pass t into your easing function.
  4. Use the result to interpolate values.
animation-loop.js
let startTime = null;
const duration = 1000; // 1 second
const startPos = 0;
const targetPos = 500;

function animate(timestamp) {
    if (!startTime) startTime = timestamp;
    const elapsed = timestamp - startTime;
    
    // 1. Calculate 't' (0 to 1)
    let t = Math.min(elapsed / duration, 1);
    
    // 2. Apply easing
    const easedT = Easing.easeOutBounce(t);
    
    // 3. Update position
    // Formula: start + (change * easedT)
    const currentPos = startPos + (targetPos - startPos) * easedT;
    
    // Render moving object...
    object.x = currentPos;
    
    if (t < 1) {
        requestAnimationFrame(animate);
    }
}

requestAnimationFrame(animate);