Mastering Easing Functions
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.
- Track
currentTimeandduration. - Calculate normalized time
t = currentTime / duration(0 to 1). - Pass
tinto your easing function. - 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);