@zakkster/lite-ease is the complete set of Robert Penner easing equations as individual, tree-shakeable ES module exports โ plus a small, zero-allocation composition layer.
It gives you:
- ๐ข 30 easing functions (10 families ร 3 variants)
- ๐งฎ Pure math:
(t: number) => numberwhere t โ [0, 1] - ๐ Composable:
lerp(a, b, easeOutBounce(t)) - ๐ก๏ธ
clamp01()wrapper for Back/Elastic overshoot - ๐
reverse(ease)creates the inverse curve - ๐ผ v1.1:
mirror,chain,blend,scaleโ zero-GC composition factories - ๐
easingslookup map for string-based access - 0๏ธโฃ Zero dependencies, pure math, no allocation in hot path
- ๐ชถ < 1 KB minified (entire library)
Part of the @zakkster/lite-* ecosystem โ micro-libraries built for deterministic, cache-friendly game development.
npm i @zakkster/lite-easeimport { easeOutBounce, easeInOutElastic, clamp01, reverse } from '@zakkster/lite-ease';
import { lerp } from '@zakkster/lite-lerp';
// Compose with any interpolation
const y = lerp(startY, endY, easeOutBounce(t));
// Clamp overshoot (Back/Elastic can exceed 1.0)
const safe = lerp(0, 255, clamp01(easeOutBack(t)));
// Create inverse curve
const myEaseOut = reverse(easeInCubic);
// String-based lookup (useful for configs/JSON)
import { easings } from '@zakkster/lite-ease';
const ease = easings[config.easing]; // 'easeOutBounce' โ function| Library | Size | Functions | Format | Install |
|---|---|---|---|---|
| bezier-easing | ~3 KB | Custom curves | Class | npm i bezier-easing |
| eases | ~2 KB | 31 | CommonJS | npm i eases |
| lite-ease | < 1 KB | 31 + composition | ESM, tree-shakeable | npm i @zakkster/lite-ease |
| Family | easeIn | easeOut | easeInOut |
|---|---|---|---|
| Sine | easeInSine |
easeOutSine |
easeInOutSine |
| Quad | easeInQuad |
easeOutQuad |
easeInOutQuad |
| Cubic | easeInCubic |
easeOutCubic |
easeInOutCubic |
| Quart | easeInQuart |
easeOutQuart |
easeInOutQuart |
| Quint | easeInQuint |
easeOutQuint |
easeInOutQuint |
| Expo | easeInExpo |
easeOutExpo |
easeInOutExpo |
| Circ | easeInCirc |
easeOutCirc |
easeInOutCirc |
| Back | easeInBack |
easeOutBack |
easeInOutBack |
| Elastic | easeInElastic |
easeOutElastic |
easeInOutElastic |
| Bounce | easeInBounce |
easeOutBounce |
easeInOutBounce |
linear(t)โ Identity functionclamp01(t)โ Clamp to [0, 1]. Back/Elastic overshoot safely.reverse(ease)โ Create the inverse:reverse(easeIn) โ easeOuteasingsโRecord<string, EasingFunction>for dynamic lookup
Each helper is a factory: it pre-computes any constants and returns a closure that does zero allocation per call. The returned function is what you call in your hot path.
โ ๏ธ Build once, call many. Don't putmirror(...),chain(...),blend(...), orscale(...)inside yourrequestAnimationFrameloop โ that allocates a fresh closure every frame and defeats the design. Build the composed easing in init/module scope, then call the returned function each frame.
Plays the curve forward in the first half, then backward โ a seamless ping-pong (0 โ 1 โ 0).
import { mirror, easeInOutQuad } from '@zakkster/lite-ease';
const pingPong = mirror(easeInOutQuad);
// pingPong(0) === 0
// pingPong(0.5) โ 1
// pingPong(1) === 0clamp: true clamps each half to [0, 1] โ useful when wrapping easeOutBack or easeOutElastic to suppress overshoot.
Sequential chain: easeA drives t โ [0, 0.5], easeB drives t โ [0.5, 1].
import { chain, easeInQuad, easeOutBounce } from '@zakkster/lite-ease';
const windAndDrop = chain(easeInQuad, easeOutBounce);
// First half: smooth wind-up. Second half: bounce settle.clamp: true is recommended when either curve overshoots โ clamps each half to its [0, 0.5] / [0.5, 1] range so overshoot can't bleed across the midpoint.
Linear crossfade between two curves. weight is clamped to [0, 1] once at init and stored โ no per-call clamp cost.
import { blend, linear, easeOutElastic } from '@zakkster/lite-ease';
const subtleElastic = blend(linear, easeOutElastic, 0.3);
// 70% linear + 30% elastic โ keeps the bounce flavor without the full overshoot.Remaps an easing to a sub-segment of the timeline. Outside the segment, output is locked to the boundary value (pre-computed at init). Throws if toT <= fromT.
import { scale, easeOutBounce } from '@zakkster/lite-ease';
const dropAt40Percent = scale(easeOutBounce, 0.4, 0.9);
// dropAt40Percent(t) โ 0 for t <= 0.4
// dropAt40Percent(t) โ 1 for t >= 0.9
// drops/bounces between 0.4 and 0.9 of the master timelineIdeal for staggered animation sequences where multiple elements share a master t and each starts/ends at a different point.
31 easing functions, 1M calls each:
All functions: < 0.01ms per call (pure arithmetic)
No allocation, no branching (except Bounce/Elastic)
Tree-shakeable: unused functions are eliminated by bundlers
Composition helpers (mirror/chain/blend/scale):
Factory cost paid once at init.
Returned closure: zero allocation per call, one inner ease() invocation.
Full declarations included in LiteEase.d.ts. The EasingFunction type alias is exported for your own composed easings.
See llms.txt for AI-optimized metadata and usage examples.
MIT