원클릭으로
gsap-easing
// Use when implementing animation easing functions, custom easing, elastic effects, bounce animations, or controlling animation velocity curves.
// Use when implementing animation easing functions, custom easing, elastic effects, bounce animations, or controlling animation velocity curves.
Use when setting up GSAP in a project, installing GSAP, registering plugins, configuring defaults, or implementing GSAP best practices and workflows.
Use when implementing web animations, timeline sequencing, scroll-triggered animations, SVG animations, layout transitions, or using GSAP, ScrollTrigger, ScrollSmoother, SplitText, Flip, DrawSVG, MorphSVG, MotionPath, or @gsap/react useGSAP hook.
Use when implementing SVG animations, stroke drawing, path morphing, motion along paths, or using DrawSVGPlugin, MorphSVGPlugin, MotionPathPlugin.
Use when implementing text animations, text effects, character/word/line animations, text reveals, scrambling effects, or using SplitText, TextPlugin, ScrambleTextPlugin.
Use when implementing GSAP core animations, tweens, timeline sequencing, playback controls, or when using gsap.to(), gsap.from(), gsap.fromTo(), gsap.set(), gsap.timeline().
Use when implementing drag interactions, draggable elements, throwing with inertia, bounds enforcement, drag-based UI, or using Draggable and InertiaPlugin.
| name | gsap-easing |
| description | Use when implementing animation easing functions, custom easing, elastic effects, bounce animations, or controlling animation velocity curves. |
Easing functions control how animations progress over time. GSAP provides extensive built-in eases plus plugins for custom curves, elastic effects, and bounce animations.
// Power0 - Linear (no easing)
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'none' // Same as 'power0'
})
// Power1 - Default
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power1.out' // GSAP default
})
// Power2
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power2.out'
})
// Power3
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power3.out'
})
// Power4 - Strongest curve
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power4.out'
})
// In - Slow start, fast end
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power2.in'
})
// Out - Fast start, slow end
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power2.out'
})
// InOut - Slow both ends, fast middle
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'power2.inOut'
})
// Back.out - Overshoots target then settles
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'back.out(1.7) // 1.7 is overshoot amount
})
// Back.in - Pulls back first
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'back.in(1.7)'
})
// Back.inOut - Both directions
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'back.inOut(1.7)'
})
// Elastic.out - Springy overshoot
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'elastic.out(1, 0.3)'
// First param: amplitude (1 = no overshoot)
// Second param: period (lower = more wiggles)
})
// Elastic.in - Elastic start
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'elastic.in(1, 0.3)'
})
// Elastic.inOut - Both directions
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'elastic.inOut(1, 0.3)'
})
// Bounce.out - Ball-like bounce at end
gsap.to('.box', {
y: -200,
duration: 1,
ease: 'bounce.out'
})
// Bounce.in - Bounce at start
gsap.to('.box', {
y: -200,
duration: 1,
ease: 'bounce.in'
})
// Bounce.inOut - Bounce both ends
gsap.to('.box', {
y: -200,
duration: 1,
ease: 'bounce.inOut'
})
// Expo.out - Very strong ease out
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'expo.out'
})
// Expo.in - Very strong ease in
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'expo.in'
})
// Expo.inOut - Both very strong
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'expo.inOut'
})
// Circ - Circular easing
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'circ.out'
})
// Sine - Gentle sine wave
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'sine.out'
})
// 5 discrete steps
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'steps(5)'
})
// Start at top of step
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'steps(5, start)'
})
// End at top of step
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'steps(5, end)'
})
// Both
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'steps(5, both)'
})
gsap.to('.sprite', {
backgroundPosition: `-${frameWidth * 7}px 0`,
duration: 0.8,
ease: 'steps(7)', // 7 frames
repeat: -1
})
npm install gsap
import { EasePack } from 'gsap/EasePack'
gsap.registerPlugin(EasePack)
// SlowMo - Decelerates, holds, accelerates
gsap.to('.box', {
x: 200,
duration: 2,
ease: 'slow(0.7, 0.7, false)'
// First: ease portion
// Second: hold portion
// Third: ease out portion (true/false)
})
// RoughEase - Jagged, organic feel
gsap.to('.box', {
x: 200,
duration: 2,
ease: 'rough({
template: 'power1.out',
strength: 1,
points: 20,
taper: 'both',
randomize: true,
clamp: false
})
})
// Pre-configured rough eases
gsap.to('.box', {
x: 200,
duration: 2,
ease: 'rough.ease' // Simplified
})
// ExpoScale - For scaling animations
gsap.to('.box', {
scale: 5,
duration: 2,
ease: 'expoScale(0.5, 3, 'power2.inOut)'
// From scale, to scale, ease function
})
npm install gsap
import { CustomEase } from 'gsap/CustomEase'
gsap.registerPlugin(CustomEase)
// Create from SVG path
CustomEase.create('myEase', 'M0,0 C0.5,0 0.5,1 1,1')
gsap.to('.box', {
x: 200,
duration: 1,
ease: 'myEase'
})
CustomEase.create('myEase', [
{ x: 0, y: 0 },
{ x: 0.3, y: 0.2, controlPoint: { x: 0.15, y: 0 } },
{ x: 0.7, y: 0.8, controlPoint: { x: 0.85, y: 1 } },
{ x: 1, y: 1 }
])
// Visual method - get path from UI
CustomEase.create('visualEase', 'M0,100 C50,0 100,100 100,100')
import { CustomWiggle } from 'gsap/CustomWiggle'
gsap.registerPlugin(CustomWiggle)
// Create wiggle ease
CustomWiggle.create('myWiggle', {
wiggles: 2,
amplitude: 1
})
gsap.to('.box', {
x: 200,
rotation: 20,
duration: 2,
ease: 'myWiggle'
})
import { CustomBounce } from 'gsap/CustomBounce'
gsap.registerPlugin(CustomBounce)
// Create custom bounce
CustomBounce.create('myBounce', {
squash: 2,
bounce: 5
})
gsap.to('.ball', {
y: -200,
duration: 1,
ease: 'myBounce'
})
| Effect | Recommended Ease |
|---|---|
| Default UI | power2.out |
| Entrance | back.out(1.7) or power3.out |
| Exit | power2.in |
| Attention | elastic.out(1, 0.3) |
| Playful | bounce.out |
| Smooth | sine.inOut |
| Punchy | power4.out |
| Organic | rough.ease |
| Subtle | power1.inOut |
| Natural | expo.inOut |
| Step | steps(5) |
| Property | Recommended Ease |
|---|---|
| Position (x,y) | power2.out, back.out |
| Scale | back.out(1.7), elastic.out |
| Rotation | elastic.out, back.out |
| Opacity | power2.out, sine.out |
| Color | power1.out |
| Filter | power1.out |
const tl = gsap.timeline()
tl.to('.box1', {
x: 100,
duration: 1,
ease: 'power2.out' // Individual ease
})
.to('.box2', {
x: 100,
duration: 1,
ease: 'back.out' // Different ease
})
const tl = gsap.timeline({
defaults: {
ease: 'power2.out', // Default for all tweens
duration: 1
}
})
tl.to('.box1', { x: 100 }) // Uses default ease
.to('.box2', {
x: 100,
ease: 'back.out' // Overrides default
})
// Keyframes with per-keyframe ease
gsap.to('.box', {
keyframes: [
{ x: 100, ease: 'power2.out' },
{ y: 100, ease: 'back.out' },
{ x: 0, y: 0, ease: 'power2.out' }
],
easeEach: 'power1.out' // If individual ease not specified
})
const eases = [
'none',
'power1.out',
'power2.out',
'power3.out',
'power4.out',
'back.out(1.7)',
'elastic.out(1, 0.3)',
'bounce.out'
]
eases.forEach((ease, i) => {
gsap.to(`.box-${i}`, {
x: 200,
duration: 1,
ease: ease,
delay: i * 1.2
})
})
function visualizeEase(easeName) {
const path = []
for (let i = 0; i <= 100; i++) {
const progress = i / 100
const easedValue = gsap.parseEase(easeName)(progress)
path.push({ x: progress * 100, y: (1 - easedValue) * 100 })
}
// Draw SVG path
const d = 'M' + path.map(p => `${p.x},${p.y}`).join(' L')
console.log(d)
}
visualizeEase('power2.out')
// ❌ Complex eases on many elements
gsap.to('.many-boxes', {
x: 200,
ease: 'elastic.out(1, 0.3)', // Computationally expensive
stagger: 0.05
})
// ✅ Simpler eases for performance
gsap.to('.many-boxes', {
x: 200,
ease: 'power2.out', // Faster
stagger: 0.05
})
// Parse and cache ease
const myEase = gsap.parseEase('power2.out')
// Use cached ease
gsap.to('.box', {
x: 200,
ease: myEase
})
gsap.from('.modal', {
scale: 0,
opacity: 0,
duration: 0.8,
ease: 'back.out(1.7)'
})
const btn = document.querySelector('.button')
btn.addEventListener('mouseenter', () => {
gsap.to(btn, {
scale: 1.1,
duration: 0.3,
ease: 'elastic.out(1, 0.5)'
})
})
btn.addEventListener('mouseleave', () => {
gsap.to(btn, {
scale: 1,
duration: 0.3,
ease: 'power2.out'
})
})
gsap.to(window, {
scrollTo: { y: target },
duration: 1,
ease: 'power2.inOut'
})
gsap.to('.ball', {
y: 500,
duration: 1.5,
ease: 'bounce.out'
})
// ❌ Elastic for subtle hover
gsap.to('.link', {
color: '#ff0000',
ease: 'elastic.out(1, 0.3)',
duration: 0.3
})
// ✅ Use appropriate ease
gsap.to('.link', {
color: '#ff0000',
ease: 'power2.out',
duration: 0.3
})
// ❌ Using in for entrance
gsap.from('.box', {
opacity: 0,
ease: 'power2.in' // Wrong direction!
})
// ✅ Use out for entrance
gsap.from('.box', {
opacity: 0,
ease: 'power2.out'
})
// ❌ Too much overshoot
gsap.to('.box', {
x: 200,
ease: 'back.out(5)' // Too aggressive!
})
// ✅ Reasonable overshoot
gsap.to('.box', {
x: 200,
ease: 'back.out(1.7)' // Sweet spot
})
| Ease | Description |
|---|---|
none | Linear (no easing) |
power1.out | Default GSAP ease |
power2.out | Standard UI ease |
back.out(1.7) | Overshoots target |
elastic.out(1, 0.3) | Springy oscillation |
bounce.out | Ball-like bounce |
expo.out | Very strong ease |
sine.out | Gentle sine wave |
steps(5) | Discrete steps |
circ.out | Circular easing |
rough.ease | Organic, jagged |
slow(0.7) | Decelerate-hold-accelerate |