
Security News
Socket Releases Free Certified Patches for Critical vm2 Sandbox Escape
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.
@penner/easing
Advanced tools
Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters
Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters and tree-shakeable exports.
npm install @penner/easing
import { back, bounce, spring } from "@penner/easing";
// Each family is callable with a config and returns { in, out, inOut, outIn }
const bounceOut = bounce({ bounces: 4, decay: 0.95 }).out;
const backOut = back({ overshoot: 0.15 }).out;
const springOut = spring({ bounces: 4, decay: 0.9 }).out;
// Defaults are also available as properties — no call needed
const defaultBackOut = back.out;
// Use in animations
const progress = bounceOut(0.5); // Returns the eased value at t=0.5
Custom polynomial easings with any exponent, including fractional powers.
import { power } from "@penner/easing";
// Create custom power families
const sqrt = power({ exponent: 0.5 }); // Square root easing
const custom = power({ exponent: 2.5 }); // t^2.5 easing
const sqrtOut = sqrt.out;
const customIn = custom.in;
// All variants
const fam = power({ exponent: 1.7 });
const easeIn = fam.in;
const easeOut = fam.out;
const easeInOut = fam.inOut;
const easeOutIn = fam.outIn;
Unified family that combines Power's exponent with Back's anticipation. For exponent > 1, the curve dips below 0 (anticipation) before accelerating to 1 — generalizing classic cubic Back to any power.
import { powerBack } from "@penner/easing";
// Defaults (exponent: 3, overshoot: 0.1) — equivalent to classic Back
const easeIn = powerBack.in;
const easeOut = powerBack.out;
// Custom: stronger anticipation with a steeper acceleration
const snappy = powerBack({ exponent: 4, overshoot: 0.2 });
const snappyOut = snappy.out;
const snappyInOut = snappy.inOut;
interface PowerBackConfig {
exponent: number; // Power exponent (> 1 for overshoot; default 3)
overshoot: number; // Anticipation depth as a fraction (default 0.1)
}
Setting overshoot: 0 collapses to pure power easing (u^n); exponent: 3 with a custom overshoot matches classic back.
Creates overshoot effects where the animation goes beyond its target before settling.
import { back } from "@penner/easing";
// Default overshoot (10%) — use the family's default variants directly
const easeOut = back.out;
// Custom overshoot (20%)
const easeOutBig = back({ overshoot: 0.2 }).out;
// All variants
const easeIn = back({ overshoot: 0.15 }).in;
const easeInOut = back({ overshoot: 0.1 }).inOut;
const easeOutIn = back({ overshoot: 0.1 }).outIn;
Physics-based bouncing with configurable energy loss and number of bounces.
import { bounce } from "@penner/easing";
// Default bounce (4 bounces, 95% decay)
const easeOut = bounce.out;
// Custom bounce
const easeOutBouncy = bounce({
bounces: 6,
decay: 0.8,
}).out;
// All variants
const easeIn = bounce({ bounces: 3, decay: 0.9 }).in;
const easeInOut = bounce.inOut;
const easeOutIn = bounce.outIn;
Damped oscillations with configurable bounces and decay.
import { spring } from "@penner/easing";
// Default spring (4 bounces, 95% decay)
const easeOut = spring.out;
// Custom oscillations
const easeOutCustom = spring({
bounces: 6,
decay: 0.9,
}).out;
// Critically damped (no oscillation)
const easeOutSmooth = spring({ bounces: 0 }).out;
// All variants
const easeIn = spring.in;
const easeInOut = spring.inOut;
const easeOutIn = spring.outIn;
Overdamped spring easing for smooth, non-oscillating motion.
import { overdamped } from "@penner/easing";
// Default overdamped spring
const easeOut = overdamped();
// Custom damping ratio and settling rate
const heavy = overdamped({ zeta: 3, settlingRate: 8 });
Classic polynomial and trigonometric easing functions. Each is a StandardEasingFamily with .in, .out, .inOut, and .outIn properties.
import { quadratic, cubic, quartic, quintic, sine, circular, expo } from "@penner/easing";
// Access variants as properties (not function calls)
const quadOut = quadratic.out;
const cubicIn = cubic.in;
const quartInOut = quartic.inOut;
const sineOutIn = sine.outIn;
Simple easing functions exported as single EasingFn values (not families).
import { linear, smoothstep, smootherstep } from "@penner/easing";
const value = smoothstep(0.5); // Hermite interpolation
Configurable exponential easing with utility functions.
import { expo, makeExpoEaseOut } from "@penner/easing";
// Standard expo family
const easeOut = expo.out;
const easeIn = expo.in;
// Custom exponential ease-out
const customExpo = makeExpoEaseOut(10);
Physics-based easing functions derived from force models. These are experimental and their APIs may change.
import { force, compression, viscous, viscousPower, swim } from "@penner/easing";
Includes force, compression, viscous, viscousDrag, viscousPower, swim, and swimAnalytic.
Import only what you need to keep bundle sizes small:
// Import specific families
import { bounce, spring } from "@penner/easing";
// Import standard easings alongside physics-based ones
import { quadratic, cubic, back } from "@penner/easing";
interface BounceConfig {
bounces?: number; // Number of bounces (default: 4)
decay?: number; // Total height decay as fraction 0-1 (default: 0.95)
}
interface SpringConfig {
bounces?: number; // Visible oscillation half-cycles (default: 4)
decay?: number; // Total amplitude decay as fraction 0-1 (default: 0.95)
}
easingKit wraps any easing function into a callable bundle with CSS linear() approximations, velocity curve, and derivative functions — all lazily computed and cached on first access.
import { easingKit, spring } from "@penner/easing";
// Destructure the CSS strings you need
const { easing, velocity } = easingKit({ easingFn: spring.out() });
// Use easing for position, velocity for scale
element.style.animation = "move 2s both, scale 2s both";
element.style.animationTimingFunction = `${easing}, ${velocity}`;
@keyframes move {
to {
translate: 200px;
}
}
@keyframes scale {
from {
scale: 0.8;
}
}
// Or with the Web Animations API
element.animate([{ translate: "0px" }, { translate: "200px" }], {
duration: 2000,
easing,
fill: "both",
});
element.animate([{ scale: 0.8 }, { scale: 1 }], { duration: 2000, easing: velocity, fill: "both" });
// Or keep the kit for callable use and derivatives
const kit = easingKit({ easingFn: spring.out() });
kit(0.5); // call as a plain easing function
kit.velocityFn(0.5); // numerical 1st derivative
kit.accelerationFn(0.5); // numerical 2nd derivative
You can supply exact analytical derivatives when the particular math formulas are known:
const kit = easingKit({
easingFn: (t) => t * t,
velocityFn: (t) => 2 * t, // exact derivative of t²
});
interface EasingKitOptions {
easingFn: EasingFn;
velocityFn?: VelocityFn; // analytical 1st derivative
accelerationFn?: AccelerationFn; // analytical 2nd derivative
jerkFn?: JerkFn; // analytical 3rd derivative
meta?: EasingKitMeta; // factory name + args for serialization
}
type EasingKit = EasingFn & {
readonly easingFn: EasingKit; // self-reference for destructuring
readonly easing: CSSEasing; // CSS linear() string
readonly velocityFn: VelocityFn;
readonly accelerationFn: AccelerationFn;
readonly jerkFn: JerkFn;
readonly velocity: CSSEasing; // velocity as CSS linear()
readonly meta: EasingKitMeta;
readonly toString: () => CSSEasing;
};
Standalone utilities for working with easing functions. For bundled derivatives and CSS, see EasingKit above.
import {
reverseEasingFn,
mirrorEasingFnToRight,
mirrorEasingFnToLeft,
clamp01,
easingFnToCssLinear,
createVelocityFn,
createAccelerationFn,
createJerkFn,
softsignClamp,
pruneColinearPoints,
progressWave,
} from "@penner/easing";
// Reverse an easing function (swap start and end)
const myEaseIn = reverseEasingFn(quadratic.out);
// Mirror an easing to the right (ease-in becomes ease-in-out)
const myEaseInOut = mirrorEasingFnToRight(quadratic.in);
// Clamp values to 0-1 range
const safe = clamp01(someValue);
// Convert an easing function to a CSS linear() approximation
const css = easingFnToCssLinear(bounce.out());
// Create individual derivative functions
const velocity = createVelocityFn(bounce.out());
const acceleration = createAccelerationFn(bounce.out());
const jerk = createJerkFn(bounce.out());
The package also exports lower-level utilities for specialized use cases:
pennerToSpring, springToPenner — convert between Penner easing parameters and spring physics parametersfitCubicBezier — fit a cubic Bézier to an easing functionvelocityToRgb, velocityToHslString, hslToRgb — color utilities for visualizing easing derivativessolveBackStrength, backEaseIn, backEaseInVelocityspringFirstPeak, amplitudeRatio, dampingRate, settlingPhaseCorrectiongetExpoEaseOutStartSlope, getExpoEaseOutEndSlope, getExpoEaseOutMetadata@penner/classic-easing — the original Penner equations with classic naming conventions (easeOutQuad, easeInBounce, etc.)@penner/responsive-easing — dynamically fuses head/tail easing curves with C¹ continuity, built on top of this packageIf you're migrating from classic Penner easing functions:
// Old: easeOutBack(t, b, c, d, s)
// New:
const backOut = back({ overshoot: s * 0.1 }).out; // Convert strength to overshoot fraction
const result = b + c * backOut(t / d);
// Old: easeOutBounce(t, b, c, d)
// New:
const bounceOut = bounce.out; // Uses sensible defaults
const result = b + c * bounceOut(t / d);
MIT - see LICENSE file for details.
FAQs
Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters
We found that @penner/easing demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.

Research
Five malicious NuGet packages impersonate Chinese .NET libraries to deploy a stealer targeting browser credentials, crypto wallets, SSH keys, and local files.

Security News
pnpm 11 turns on a 1-day Minimum Release Age and blocks exotic subdeps by default, adding safeguards against fast-moving supply chain attacks.