Claude-skill-registry animejs-v4
Anime.js 4.0 animations for Web Components — drag-drop, click feedback, swaps, cancelable motion. Use when adding animations, drag interactions, visual feedback, or motion to custom elements. Combines with web-components-architecture for lifecycle cleanup.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/animejs-v4" ~/.claude/skills/majiayu000-claude-skill-registry-animejs-v4 && rm -rf "$T"
manifest:
skills/data/animejs-v4/SKILL.mdsource content
Anime.js 4.0 for Web Components
Installation
npm i animejs
import { animate, createTimeline, stagger, createSpring, createDraggable } from 'animejs'; import { createDrawable, createMotionPath, morphTo, splitText, onScroll } from 'animejs';
Core API
Basic Animation
animate('.el', { x: 250, y: 100, rotate: 90, scale: 1.5, opacity: 0.5, backgroundColor: '#FFF', duration: 1000, delay: 200, ease: 'outQuad', loop: true, alternate: true });
Per-Property Control
animate('.el', { x: { from: -100, to: 100, duration: 800 }, rotate: { from: 0, to: 360, ease: 'inOutCirc' }, scale: { to: 1.5, delay: 200 } });
Keyframes
animate('.el', { y: [0, -50, 0], scale: [1, 1.2, 1], duration: 1000 });
Stagger
animate('.items', { y: -20, opacity: [0, 1], delay: stagger(100), // Sequential delay: stagger(100, { from: 'center' }), // From center delay: stagger(50, { grid: [5, 5] }) // Grid layout });
Function-Based Values
animate('.items', { x: (el, i, total) => i * 50, rotate: (el, i) => i % 2 === 0 ? 45 : -45 });
Playback Control
const anim = animate('.el', { x: 100, autoplay: false }); anim.play(); anim.pause(); anim.reverse(); anim.restart(); anim.seek(500); // Seek to 500ms anim.seek('50%'); // Seek to 50%
| Method | Behavior |
|---|---|
| Stop immediately, keep current inline styles |
| Stop and remove all inline styles |
| Jump to final values immediately |
Callbacks & Promises
animate('.el', { x: 100, onBegin: (anim) => {}, onUpdate: (anim) => {}, onComplete: (anim) => {} }); await animate('.el', { x: 100 }); // Promise-based
Timeline
const tl = createTimeline({ loop: true, alternate: true }); tl.add('.box1', { x: 100 }) .add('.box2', { y: 50 }, '-=200') // 200ms before previous ends .add('.box3', { scale: 2 }, '+=100') // 100ms after previous .add('.box4', { rotate: 90 }, 500); // At 500ms absolute tl.label('myLabel', 1000); tl.call(() => console.log('done'), 2000);
Easings & Springs
Built-in:
linear, in, out, inOut, outIn (with power: out(3)).
Named: inQuad, outQuad, inOutQuad, inCubic, outExpo, inOutElastic, outBounce, outBack.
// Spring physics animate('.el', { x: 100, ease: createSpring({ stiffness: 400, damping: 25 }) });
Spring Presets
const springs = { click: createSpring({ stiffness: 600, damping: 30 }), move: createSpring({ stiffness: 300, damping: 25 }), drop: createSpring({ stiffness: 400, damping: 20 }), settle: createSpring({ stiffness: 200, damping: 25 }), bounce: createSpring({ stiffness: 500, damping: 10 }) };
Web Component Integration
Animation Manager Pattern
Always cancel existing animations before starting new ones. Use a WeakMap to track animations per element without memory leaks.
class AnimationManager { #anims = new WeakMap(); animate(el, props, key = 'main') { const map = this.#anims.get(el) || {}; map[key]?.cancel(); // Cancel existing const anim = animate(el, props); map[key] = anim; this.#anims.set(el, map); return anim; } cancel(el, key = 'main') { this.#anims.get(el)?.[key]?.cancel(); } revert(el, key = 'main') { this.#anims.get(el)?.[key]?.revert(); } }
Component Lifecycle
Follows
web-components-architecture skill — use disconnectedCallback for cleanup:
class AnimatedCard extends HTMLElement { #anim = null; animate(props) { this.#anim?.cancel(); this.#anim = animate(this, props); return this.#anim; } disconnectedCallback() { this.#anim?.revert(); // Clean up inline styles } }
Drag-and-Drop Animations
Drag Start (Lift)
function animateDragStart(card) { return animate(card, { scale: 1.12, rotate: 8, boxShadow: '0 20px 50px rgba(0,0,0,0.3)', duration: 150, ease: 'out(3)' }); }
During Drag — Direct Transform (60fps)
Do NOT use
for pointer tracking. Set transform directly for smooth motion:animate()
function updateDragPosition(el, x, y) { el.style.transform = `translate(${x}px, ${y}px) scale(1.12) rotate(8deg)`; }
Drop Animation
function animateDrop(card) { return animate(card, { x: 0, y: 0, scale: [1.12, 0.95, 1], rotate: [8, -2, 0], boxShadow: '0 2px 8px rgba(0,0,0,0.1)', duration: 350, ease: 'outBack' }); }
Return to Origin
function animateReturn(card) { return animate(card, { x: 0, y: 0, scale: 1, rotate: 0, duration: 400, ease: 'outBack' }); }
Card Swap (FLIP Pattern)
async function animateSwap(cardA, cardB, slotA, slotB) { const rectA = cardA.getBoundingClientRect(); const rectB = cardB.getBoundingClientRect(); // DOM swap first slotA.appendChild(cardB); slotB.appendChild(cardA); const newRectA = cardA.getBoundingClientRect(); const newRectB = cardB.getBoundingClientRect(); // Animate from old positions await Promise.all([ animate(cardA, { x: [rectA.left - newRectA.left, 0], y: [rectA.top - newRectA.top, 0], scale: [1.1, 0.95, 1], duration: 400, ease: 'outBack' }), animate(cardB, { x: [rectB.left - newRectB.left, 0], y: [rectB.top - newRectB.top, 0], scale: [1, 1.05, 1], duration: 400, ease: 'outBack' }) ]); }
Slot Hover Feedback
function animateSlotHover(slot, isOver) { animate(slot, { scale: isOver ? 1.03 : 1, borderColor: isOver ? '#4CAF50' : '#999', duration: 150, ease: 'out(2)' }); }
Click Animations
// Bounce feedback animate(card, { scale: [1, 1.15, 1], rotate: [0, 5, -5, 0], duration: 400, ease: 'outElastic(1, 0.5)' }); // Disabled shake animate(card, { x: [0, -8, 8, -6, 6, 0], duration: 300, ease: 'linear' });
Scroll-Driven Animation
animate('.el', { x: 300, autoplay: onScroll({ target: '.el', enter: 'bottom', leave: 'top', sync: true }) });
SVG Animations
animate(createDrawable('path'), { draw: '0 1' }); // Draw path animate('.el', { ...createMotionPath('.path') }); // Motion path animate('.shape1', { d: morphTo('.shape2') }); // Morph shapes
Text Splitting
const { chars } = splitText('.text', { chars: true }); animate(chars, { y: [20, 0], opacity: [0, 1], delay: stagger(30) });
Built-in Draggable
createDraggable('.el', { x: true, y: true, snap: 50, container: '.bounds', releaseEase: createSpring({ stiffness: 120, damping: 6 }), onDrag: (d) => {}, onRelease: (d) => {} });
V3 to V4 Migration
| V3 | V4 |
|---|---|
| |
| |
| |
| |
| |
| or |