🚀 Big News:Socket Has Acquired Secure Annex.Learn More →
Socket
Book a DemoSign in
Socket

@penner/easing

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@penner/easing

Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

@penner/easing

Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters and tree-shakeable exports.

npm version

Features

  • Tree-shakeable: Import only the easing functions you need
  • Physics-based: Configure easings with intuitive physical parameters
  • TypeScript: Full type safety with comprehensive interfaces
  • Modern API: Clean factory functions with sensible defaults
  • High performance: Optimized implementations with numerical stability

Installation

npm install @penner/easing

Quick Start

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

Easing Families

Power

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;

Power-Back

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.

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;

Bounce

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;

Spring

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

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 });

Standard Easings

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;

Linear, Smoothstep, Smootherstep

Simple easing functions exported as single EasingFn values (not families).

import { linear, smoothstep, smootherstep } from "@penner/easing";

const value = smoothstep(0.5); // Hermite interpolation

Exponential

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);

Force-Based Easings (Experimental)

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.

Tree-Shaking

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";

Configuration Interfaces

BounceConfig

interface BounceConfig {
  bounces?: number; // Number of bounces (default: 4)
  decay?: number; // Total height decay as fraction 0-1 (default: 0.95)
}

SpringConfig

interface SpringConfig {
  bounces?: number; // Visible oscillation half-cycles (default: 4)
  decay?: number; // Total amplitude decay as fraction 0-1 (default: 0.95)
}

EasingKit

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²
});

EasingKit types

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;
};

Utility Functions

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());

Advanced

The package also exports lower-level utilities for specialized use cases:

  • Spring conversion: pennerToSpring, springToPenner — convert between Penner easing parameters and spring physics parameters
  • Bezier fitting: fitCubicBezier — fit a cubic BĂ©zier to an easing function
  • Heat map colors: velocityToRgb, velocityToHslString, hslToRgb — color utilities for visualizing easing derivatives
  • Back helpers: solveBackStrength, backEaseIn, backEaseInVelocity
  • Spring helpers: springFirstPeak, amplitudeRatio, dampingRate, settlingPhaseCorrection
  • Expo helpers: getExpoEaseOutStartSlope, 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 package

Migration from Legacy Penner Functions

If 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);

License

MIT - see LICENSE file for details.

Keywords

easing

FAQs

Package last updated on 18 Apr 2026

Did you know?

Socket

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.

Install

Related posts