# Animejs

> Anime.js adapter patterns for FrameVideo. Use when writing Anime.js animations or timelines inside FrameVideo compositions, registering animations on window.__fvAnime, making Anime.js seek-driven and deterministic, or translating Anime.js examples into render-safe FrameVideo HTML.

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

---


# Anime.js for FrameVideo

## When To Use

Use Anime.js for:

- **Lightweight animations** — smaller bundle size than GSAP (17KB vs 45KB)
- **Simple DOM/SVG motion** — element entrances, transforms, opacity
- **Compact syntax** — cleaner for straightforward animations
- **Porting Anime.js examples** — user provides Anime.js code to adapt
- **File size constraints** — when every KB matters

## Do NOT Use

Avoid Anime.js for:

- **Complex timeline sequencing** — GSAP has better timeline control and labels
- **Default choice** — use `gsap` unless you have specific reason for Anime.js
- **3D or WebGL** — use `three`
- **CSS-only decoration** — use `css-animations`
- **GPU shaders** — use `typegpu`

---

## Quick Start

Basic Anime.js animation in FrameVideo:

```html
<div class="clip" data-start="0" data-duration="3">
  <div class="mark">Animate me</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/animejs@4.0.2/lib/anime.iife.min.js"></script>
<script>
  const anim = anime({
    targets: ".mark",
    translateX: 280,
    rotate: "1turn",
    opacity: [0, 1],
    duration: 1200,
    easing: "easeOutExpo",
    autoplay: false,  // REQUIRED for FrameVideo
  });

  window.__fvAnime = window.__fvAnime || [];
  window.__fvAnime.push(anim);  // Register for seeking
</script>
```

**Key points:**
1. Set `autoplay: false`
2. Register on `window.__fvAnime` array
3. Use finite durations

---

## Contract

- Create animations or timelines synchronously during composition initialization.
- Set `autoplay: false` so Anime.js does not advance on its own clock.
- Register every returned animation or timeline on `window.__fvAnime`.
- Use finite durations and loop counts.
- Avoid callbacks that mutate DOM based on wall-clock time, network state, or unseeded randomness.

The adapter seeks every registered instance with `instance.seek(timeMs)`, where `timeMs` is FrameVideo time in milliseconds.

## Basic Pattern

```html
<script src="https://cdn.jsdelivr.net/npm/animejs@4.0.2/lib/anime.iife.min.js"></script>
<script>
  const anim = anime({
    targets: ".mark",
    translateX: 280,
    rotate: "1turn",
    opacity: [0, 1],
    duration: 1200,
    easing: "easeOutExpo",
    autoplay: false,
  });

  window.__fvAnime = window.__fvAnime || [];
  window.__fvAnime.push(anim);
</script>
```

## Timeline Pattern

```html
<script>
  const tl = anime.timeline({
    autoplay: false,
    easing: "easeOutCubic",
  });

  tl.add({
    targets: ".title",
    translateY: [40, 0],
    opacity: [0, 1],
    duration: 650,
  }).add(
    {
      targets: ".accent",
      scaleX: [0, 1],
      duration: 450,
    },
    250,
  );

  window.__fvAnime = window.__fvAnime || [];
  window.__fvAnime.push(tl);
</script>
```

## Module Builds

If you use an ES module build, the adapter does not care how the instance was created. It only needs the returned object to expose `seek()`, `pause()`, and preferably `play()`:

```html
<script type="module">
  import { animate } from "https://cdn.jsdelivr.net/npm/animejs/+esm";

  const anim = animate(".chip", {
    x: "18rem",
    duration: 900,
    autoplay: false,
  });

  window.__fvAnime = window.__fvAnime || [];
  window.__fvAnime.push(anim);
</script>
```

## Good Uses

- Small SVG and DOM flourishes where Anime.js syntax is compact.
- Imported Anime.js examples that can be made seek-driven.
- Multiple independent micro-animations pushed into the same registry.

Use GSAP for complex scene sequencing unless the user specifically asks for Anime.js. GSAP is still the primary FrameVideo authoring path.

## Avoid

- Leaving `autoplay` at the Anime.js default.
- Depending on `anime.running` auto-discovery instead of explicit `window.__fvAnime.push(...)`.
- Infinite loops. Compute a finite repeat count from the composition duration.
- Building animations in timers, promises, event handlers, or after async asset loads.

## Validation

After editing a composition that uses Anime.js:

```bash
npx framevideo lint
npx framevideo validate
```

## Validation

After writing Anime.js animations:

```bash
npx framevideo lint      # Check registration
npx framevideo validate  # Check runtime errors
npx framevideo preview   # Scrub timeline to verify seekability
```

**Manual checks:**
1. **Registration** — verify all animations pushed to `window.__fvAnime`
2. **Autoplay disabled** — all animations have `autoplay: false`
3. **Finite loops** — no infinite `loop: true`, use counted loops
4. **Seekability** — scrub preview, animation holds at any frame

## Credits And References

- FrameVideo adapter source: `packages/core/src/runtime/adapters/animejs.ts`.
- Anime.js documentation for `autoplay`, `pause()`, and `seek()`: https://animejs.com/documentation/

