High-performance JavaScript animation library for animating CSS, SVG, canvas, React, Vue, WebGL, and any JavaScript-accessible properties.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
GSAP's advanced plugins provide specialized functionality for physics simulations, custom easing, development tools, and unique animation effects that extend the core animation system.
import {
InertiaPlugin,
Physics2DPlugin,
CustomEase,
GSDevTools,
Flip,
Observer
} from "gsap/all";
gsap.registerPlugin(InertiaPlugin, Physics2DPlugin, CustomEase, GSDevTools, Flip, Observer);Create momentum-based animations with velocity, friction, and bounds.
interface InertiaVars {
inertia?: {
[property: string]: {
velocity?: number | "auto"; // Initial velocity
min?: number; // Minimum value
max?: number; // Maximum value
bounce?: number; // Bounce strength (0-1)
friction?: number; // Friction/resistance
unitFactors?: object; // Unit conversion factors
resistance?: number; // Resistance (deprecated, use friction)
};
};
}Usage Examples:
// Basic momentum animation
gsap.to(".ball", {
duration: 2,
inertia: {
x: { velocity: 500, friction: 0.9, min: 0, max: 400 },
y: { velocity: -300, friction: 0.8, bounce: 0.5 }
}
});
// Auto-detect velocity from user interaction
let startX, startY;
element.addEventListener("pointerdown", (e) => {
startX = e.clientX;
startY = e.clientY;
});
element.addEventListener("pointerup", (e) => {
gsap.to(".element", {
duration: 3,
inertia: {
x: { velocity: "auto", friction: 0.95, min: 0, max: 500 },
y: { velocity: "auto", friction: 0.9 }
}
});
});2D physics simulation with gravity, velocity, and acceleration.
interface Physics2DVars {
physics2D?: {
velocity?: number; // Initial velocity
angle?: number; // Launch angle in degrees
gravity?: number; // Gravity strength
friction?: number; // Air resistance
acceleration?: number; // Acceleration
accelerationAngle?: number; // Acceleration direction
};
}Usage Examples:
// Projectile motion
gsap.to(".projectile", {
duration: 3,
physics2D: {
velocity: 300, // Launch speed
angle: 45, // 45-degree angle
gravity: 500 // Gravity pulls down
}
});
// Multiple projectiles
gsap.to(".particle", {
duration: 4,
physics2D: {
velocity: () => gsap.utils.random(200, 400),
angle: () => gsap.utils.random(-30, 30),
gravity: 600,
friction: 0.1
},
stagger: 0.1
});Create custom easing curves using visual editor or mathematical functions.
/**
* Create custom easing function from path data
* @param id - Unique identifier for the ease
* @param path - SVG path data or Cubic Bezier values
* @param rawPath - Optional raw path data
* @returns Custom easing function
*/
CustomEase.create(id: string, path: string, rawPath?: any): EaseFunction;
/**
* Get easing function by ID
* @param id - Ease identifier
* @returns Easing function or null
*/
CustomEase.get(id: string): EaseFunction | null;Usage Examples:
// Create custom ease from Cubic Bezier
CustomEase.create("myEase", "M0,0 C0.25,0.46 0.45,0.94 1,1");
// Use custom ease
gsap.to(".element", {
duration: 2,
x: 100,
ease: "myEase"
});
// Create from Cubic Bezier values
CustomEase.create("bounceOut", "0.68, -0.55, 0.265, 1.55");
// Complex multi-point curve
CustomEase.create("wiggle", "M0,0 C0,0 0.056,0.442 0.175,0.442 0.294,0.442 0.332,0 0.332,0 0.332,0 0.414,1 0.671,1 0.991,1 1,0 1,0");First-Last-Invert-Play technique for seamless layout animations.
/**
* Capture current state of elements
* @param targets - Elements to capture state for
* @param props - Properties to capture
* @returns State object
*/
Flip.getState(targets: string | Element | Element[], props?: string | object): FlipState;
/**
* Animate from captured state to current state
* @param state - Previously captured state
* @param vars - Animation configuration
* @returns Timeline of flip animations
*/
Flip.from(state: FlipState, vars?: Flip.Vars): gsap.core.Timeline;
/**
* Animate to a captured state
* @param state - Target state to animate to
* @param vars - Animation configuration
* @returns Timeline of flip animations
*/
Flip.to(state: FlipState, vars?: Flip.Vars): gsap.core.Timeline;
/**
* Fit one element to another's bounds
* @param fromElement - Source element
* @param toElement - Target element bounds
* @param vars - Animation configuration
* @returns Tween animation
*/
Flip.fit(fromElement: Element, toElement: Element, vars?: Flip.Vars): gsap.core.Tween;Usage Examples:
// Basic FLIP animation
const state = Flip.getState(".cards");
// Make DOM changes (add/remove/reorder elements)
container.appendChild(card); // Move card to end
// Animate from old positions to new positions
Flip.from(state, {
duration: 0.8,
ease: "power2.inOut",
stagger: 0.1
});
// Responsive layout changes
const mediaQuery = gsap.matchMedia();
mediaQuery.add("(max-width: 768px)", () => {
const state = Flip.getState(".layout-items");
// Change to mobile layout
items.forEach(item => mobileContainer.appendChild(item));
Flip.from(state, {
duration: 0.6,
ease: "power2.out"
});
});
// Element morphing
const startState = Flip.getState(".morph-element");
element.classList.add("expanded");
Flip.from(startState, { duration: 1 });Unified scroll, touch, and pointer event handling with normalization.
/**
* Create Observer instance for unified event handling
* @param vars - Observer configuration
* @returns Observer instance
*/
Observer.create(vars: Observer.Vars): Observer;
interface Observer.Vars {
target?: Element | Window; // Element to observe
type?: string; // Event types: "scroll,touch,pointer"
// Scroll events
onChangeY?: Function; // Vertical scroll change
onChangeX?: Function; // Horizontal scroll change
// Touch/pointer events
onPress?: Function; // Press start
onRelease?: Function; // Press end
onMove?: Function; // Move during press
// Configuration
tolerance?: number; // Movement tolerance
preventDefault?: boolean; // Prevent default behaviors
wheelSpeed?: number; // Mouse wheel sensitivity
// Callbacks
onToggleX?: Function; // X direction toggle
onToggleY?: Function; // Y direction toggle
onStop?: Function; // Movement stops
}Usage Examples:
// Unified scroll handling
Observer.create({
target: window,
type: "scroll,touch,pointer",
onChangeY: (self) => {
gsap.to(".parallax", {
y: -self.velocityY * 0.3,
duration: 0.8
});
},
tolerance: 10,
preventDefault: true
});
// Touch gesture detection
Observer.create({
target: ".gesture-area",
type: "touch,pointer",
onMove: (self) => {
if (self.deltaX > 50) {
// Swipe right detected
triggerSwipeRight();
}
},
tolerance: 20
});Visual timeline controls and debugging tools for development.
/**
* Create visual dev tools for debugging animations
* @param vars - DevTools configuration
* @returns GSDevTools instance
*/
GSDevTools.create(vars?: GSDevTools.Vars): GSDevTools;
interface GSDevTools.Vars {
animation?: gsap.core.Animation; // Animation to control
globalSync?: boolean; // Sync with global timeline
paused?: boolean; // Start paused
id?: string; // Unique ID
minimal?: boolean; // Minimal UI
css?: string; // Custom CSS
container?: Element; // Container element
}
/**
* Kill all GSDevTools instances
*/
GSDevTools.killAll(): void;Usage Examples:
// Create dev tools for specific animation
const tl = gsap.timeline();
tl.to(".box", { x: 100, duration: 1 })
.to(".box", { y: 100, duration: 1 })
.to(".box", { rotation: 360, duration: 1 });
GSDevTools.create({
animation: tl,
paused: true
});
// Global timeline controls
GSDevTools.create({
globalSync: true,
minimal: true
});
// Custom positioned dev tools
GSDevTools.create({
container: document.querySelector(".dev-controls"),
css: `
.gs-dev-tools {
position: fixed;
top: 10px;
right: 10px;
}
`
});Combining multiple advanced plugins for complex effects.
// Physics with bounds checking using Flip
const physicsElements = gsap.utils.toArray(".physics-element");
physicsElements.forEach(element => {
// Capture initial state
const state = Flip.getState(element);
// Apply physics
gsap.to(element, {
duration: 3,
physics2D: {
velocity: gsap.utils.random(200, 400),
angle: gsap.utils.random(0, 360),
gravity: 300
},
onUpdate: function() {
// Check bounds and use Flip for corrections
const bounds = element.getBoundingClientRect();
if (bounds.bottom > window.innerHeight) {
const correctionState = Flip.getState(element);
gsap.set(element, { y: window.innerHeight - bounds.height });
Flip.from(correctionState, { duration: 0.1 });
}
}
});
});
// Custom ease with momentum
CustomEase.create("momentumEase", "0.25, 0.46, 0.45, 0.94");
gsap.to(".momentum-element", {
duration: 2,
x: 300,
ease: "momentumEase",
onComplete: function() {
// Apply inertia after initial animation
gsap.to(this.target, {
duration: 3,
inertia: {
x: { velocity: 100, friction: 0.9 }
}
});
}
});
// Observer with dev tools for debugging
const observer = Observer.create({
type: "scroll,touch",
onChangeY: (self) => {
const progress = Math.abs(self.velocityY) / 1000;
gsap.to(".reactive-element", {
scale: 1 + progress,
rotation: self.velocityY * 0.1,
duration: 0.3
});
}
});
// Dev tools for the observer-driven animation
GSDevTools.create({
minimal: true,
animation: gsap.getById("reactive-animation")
});