# Animejs

> This skill should be used when the user asks to "animate with anime.js", "use animejs", "add an animation" with timelines/staggers/springs, "animate on scroll", "make this draggable", "animate SVG" (draw lines, morph paths, motion paths), "split text and animate it", or when working in a project that imports from "animejs". Covers the v4 API (animate, createTimeline, stagger, onScroll, createScope) and v3→v4 migration.

- Skill: `webmilmind1/animejs` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add webmilmind1/animejs`
- Raw SKILL.md: https://api.skillmd.com/api/skills/webmilmind1/animejs/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: webmilmind1 (https://skillmd.com/u/webmilmind1)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/webmilmind1/animejs

---


# Anime.js v4

Anime.js (`animejs`, v4.x) is a lightweight JavaScript animation engine for CSS properties, transforms, SVG, DOM attributes, and plain JS objects. **v4 is a full API rewrite** — there is no default `anime()` function anymore; everything is a named import.

```js
import { animate, createTimeline, createTimer, stagger, onScroll, utils, svg, text } from 'animejs';
```

Docs: https://animejs.com/documentation — installed API truth lives in `node_modules/animejs/dist/`.

## Core: animate()

```js
animate('.square', {
  x: '17rem',                       // transform shorthand (x, y, rotate, scale, skew…)
  rotate: { from: -180, to: 0 },    // per-property from/to
  scale: [ { to: 1.25, duration: 200 }, { to: 1, duration: 300 } ], // keyframes
  opacity: 0.5,
  duration: 800,
  delay: stagger(100),              // stagger across targets
  ease: 'outElastic(1, .5)',        // NOTE: 'ease', not 'easing'; no 'ease' prefix in names
  loop: 3, alternate: true,         // v3 direction:'alternate' → alternate: true
  onComplete: (anim) => {},         // callbacks are onBegin/onUpdate/onComplete/onLoop
});
```

- Targets: CSS selector, element, NodeList, array, or plain object (`animate(obj, { prop: 100, onUpdate: ... })`).
- Playback controls on the returned animation: `.play() .pause() .restart() .reverse() .seek(ms) .then()` (awaitable).
- Eases are strings: `'out'`, `'inOutQuad'`, `'outElastic(amplitude, period)'`, `'cubicBezier(...)'`, `linear()`, `steps(n)`, `irregular()`, or `createSpring({ stiffness, damping })` passed as the `ease` value (physics-based, ignores duration).

## Timelines

```js
const tl = createTimeline({ defaults: { duration: 500 }, loop: true });
tl.add('.a', { x: 100 })
  .add('.b', { y: 50 }, '-=200')   // position: absolute ms, '-=x'/'+=x', or labels
  .label('mid')
  .add('.c', { rotate: 360 }, 'mid')
  .sync(otherAnimationOrTimeline); // v3 nested anime instances → .sync()
```

## Scroll, draggable, scope

```js
animate('.el', { x: 200, autoplay: onScroll({ container: '.scroll', enter: 'bottom top', leave: 'top bottom', sync: true }) });
createDraggable('.el', { container: '.area', snap: 100 });
```

For React/Vue/SSR, wrap in a scope tied to a root ref — required for cleanup and media queries:

```jsx
useEffect(() => {
  const scope = createScope({ root }).add(() => { animate('.logo', { rotate: 360 }); });
  return () => scope.revert();
}, []);
```

## SVG and text

```js
animate(svg.createDrawable('path'), { draw: '0 1' });        // line drawing
animate('#shape', { points: svg.morphTo('#shape2') });       // morph
animate('.el', svg.createMotionPath('path'));                // follow a path
const { chars, words, lines } = text.split('h1', { chars: true });
animate(chars, { y: [16, 0], opacity: [0, 1], delay: stagger(30) });
```

## Performance picks

- `waapi.animate(...)` — same syntax, hardware-accelerated Web Animations API; prefer for simple transform/opacity animations.
- `createAnimatable('.el', { x: 200 })` — for values driven every frame (cursor followers); far cheaper than re-triggering `animate()`.
- `createTimer({ duration, onUpdate })` — clock without targets (replaces empty-target `anime()` hacks).

## utils (grab-bag, all importable via `utils.`)

`utils.get(target, prop, unit)` reads current values, `utils.set(targets, props)` sets instantly, `utils.remove(targets)` stops animations, plus `random`, `randomPick`, `shuffle`, `clamp`, `round`, `snap`, `wrap`, `mapRange`, `lerp`, `damp`, `degToRad`/`radToDeg`, `padStart`/`padEnd`, `roundPad`, `sync`, `keepTime`, `createSeededRandom`. Chainable: `utils.clamp(0, 100).round(2)` returns a composed function.

## v3 → v4 migration (the usual breakages)

| v3 | v4 |
|---|---|
| `anime({ targets: '.el', ... })` | `animate('.el', { ... })` |
| `easing: 'easeOutQuad'` | `ease: 'outQuad'` |
| `direction: 'reverse' / 'alternate'` | `reversed: true` / `alternate: true` |
| `loop: true` + `alternate` requires even loops | `loop` counts iterations independently |
| `anime.timeline()` | `createTimeline()` |
| `anime.stagger(100)` | `stagger(100)` (named import) |
| `complete: fn, update: fn` | `onComplete: fn, onUpdate: fn` |
| `anime.random(a, b)` | `utils.random(a, b)` |
| `anime.set()` / `anime.get()` | `utils.set()` / `utils.get()` |
| `anime.remove()` | `utils.remove()` |
| value like `'+=100'` string only | `{ from: x }`, `{ to: x }`, relative `'+=100'` all supported |

Full API surface (every export, grouped by module): **`references/api.md`**.

