# Motion Canvas

> Motion Canvas framework reference covering project setup, core concepts (generators, signals, refs, scene hierarchy, timing, utilities), and 2D components (shapes, paths, text, media, layout, camera, transitions, custom components). Use when building or editing Motion Canvas scenes.

- **Type:** Skill
- **Install:** `agentstack add skill-videozero-skills-motion-canvas`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [VideoZero](https://agentstack.voostack.com/s/videozero)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [VideoZero](https://github.com/VideoZero)
- **Source:** https://github.com/VideoZero/skills/tree/main/motion-canvas
- **Website:** https://videozero.ai

## Install

```sh
agentstack add skill-videozero-skills-motion-canvas
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Motion Canvas

## Base Scene Template

```ts
import {makeScene2D} from '@motion-canvas/2d';

export default makeScene2D(function* (view) {

});
```

## Generator Functions & Animation Flow

- `function*` defines a generator function
- `yield` pauses until next frame
- `yield*` delegates to another generator (composition)

```ts
export default makeScene2D(function* (view) {
  const circle = createRef();
  view.add();

  yield* circle().position.x(300, 1);
  yield* circle().position.x(-300, 1);
});
```

**Reusable animation pattern:**
```ts
function* flicker(circle: Circle, duration: number): ThreadGenerator {
  const colors = ['#e13238', '#e6a700', '#99C47A'];
  for (const color of colors) {
    circle.fill(color);
    yield* waitFor(duration);
  }
}
yield* flicker(myCircle(), 0.5);
```

## Signals System

```ts
import {createSignal} from '@motion-canvas/core';

const radius = createSignal(3);

radius();            // Get → 3
radius(5);           // Set → 5
yield* radius(4, 2); // Tween to 4 over 2 seconds
```

**Computed signals:**
```ts
const area = createSignal(() => Math.PI * radius() * radius());
```

**Signals in JSX:**
```ts
 radius() * 2} height={() => radius() * 2} />
yield* radius(200, 1); // Circle updates automatically
```

**Vector signals:**
```ts
const position = Vector2.createSignal(Vector2.up);
yield* position(Vector2.zero, 1);
```

**Reset to default:**
```ts
import {DEFAULT} from '@motion-canvas/core';
signal(DEFAULT);             // Instant reset
yield* signal(DEFAULT, 2);   // Tween to default
```

## References (Refs)

**createRef (single node):**
```ts
const circle = createRef();

yield* circle().scale(2, 0.3);
```

**makeRef (arrays):**
```ts
const circles: Circle[] = [];
{range(10).map(index => (
  
))}
yield* all(...circles.map(c => c.scale(1.5, 0.5)));
```

**createRefMap (keyed):**
```ts
const labels = createRefMap();

yield* labels.a().text('Updated A', 0.3);
```

## Scene Hierarchy

```ts
view.add();               // Add to view
container().add();         // Add to node
container().insert(, 0);   // Insert at index
circle().remove();                   // Remove
container().removeChildren();        // Remove all children
circle().reparent(newParent());      // Move to new parent
```

**Z-order:** `moveUp()`, `moveDown()`, `moveToTop()`, `moveToBottom()`, `moveTo(2)`

**Querying:**
```ts
import {is} from '@motion-canvas/2d';
const textNodes = view.findAll(is(Txt));
const firstCircle = view.findFirst(is(Circle));
```

## Save / Restore State

```ts
yield* circle().save();
yield* all(circle().position.x(300, 1), circle().scale(2, 1));
yield* circle().restore(1); // Animate back to saved state
```

## Time Events & Waiting

```ts
import {waitFor, waitUntil, useDuration} from '@motion-canvas/core';

yield* waitFor(2);                    // Wait 2 seconds
yield* waitUntil('voice-line-2');     // Wait for named event
const dur = useDuration('segment');   // Get event duration
```

## Utilities

**Random:** `useRandom(42)` → `.nextInt(10, 100)`, `.nextFloat(0, 1)`
**Logging:** `useLogger()` → `.debug()`, `.info()`, `.warn()`, `.error()`; also `debug('msg')`
**Hooks:** `useScene()` → `.getSize()`; `useTime()`
**Range:** `range(5)` → `[0,1,2,3,4]`; `range(2,5)` → `[2,3,4]`
**Threads:**
```ts
// Spawn a background thread (do NOT yield — spawn starts it automatically)
const task = spawn(function* () {
  yield* loop(Infinity, function* () {
    yield* circle().rotation(360, 2);
    circle().rotation(0);
  });
});

// Cancel a running thread
cancel(task);

// Wait for a thread to finish
yield* join(task);
```

```ts
yield a(); // run a without waiting for a
yield* waitFor(0.5); // wait 0.5s
yield* b(1); // run b
```

## Shape Components

**Circle:**
```ts

```

**Rect:**
```ts

```

**Line:**
```ts

```

**Polygon:**
```ts

```

**Grid:**
```ts
import {Grid} from '@motion-canvas/2d';

```
Animate with `start`/`end` (0-1) for drawing/erasing effects.

**Path** (SVG path data):
```ts
import {Path} from '@motion-canvas/2d';

```
Supports morphing: `yield* path().data(newPathData, 1);`

## Filters

```ts
import {blur, brightness, grayscale, sepia, contrast, saturate, hue, invert} from '@motion-canvas/2d';

yield* rect().filters([blur(0), grayscale(1)], 1); // Animated
```

See [Filters](references/FILTERS.md) for full details.

## Gradients

```ts
import {Gradient} from '@motion-canvas/2d';

const grad = new Gradient({
  type: 'linear',
  from: [-100, 0], to: [100, 0],
  stops: [{offset: 0, color: '#e13238'}, {offset: 1, color: '#68ABDF'}],
});

```

See [Gradients](references/GRADIENTS.md) for radial and conic types.

## Path Components

**Ray:** `` — animate with `start(1,1)` / `end(0,1)`
**CubicBezier:** ``
**QuadBezier:** ``
**Spline:** `` — smooth curves
**Knot:** `new Knot([x,y], sharpness)` — adjust curve sharpness within Spline

## Text Rendering

See [Txt](references/TXT.md) for full details.

```ts

```

## Custom Components

```ts
export class Switch extends Node {
  @initial(false) @signal()
  public declare readonly initialState: SimpleSignal;

  public constructor(props?: SwitchProps) {
    super({...props});
  }

  public *toggle(duration: number) { /* animation logic */ }
}
```

**Decorators** (import from `@motion-canvas/2d`): `@signal()`, `@initial(value)`, `@colorSignal()`, `@vector2Signal()`

```ts
import {Node, NodeProps, initial, signal} from '@motion-canvas/2d';
```

## Scene Transitions

```ts
import {slideTransition, fadeTransition, Direction} from '@motion-canvas/core';
yield* slideTransition(Direction.Left);
```

**All transitions** (from `@motion-canvas/core`):
- `slideTransition(Direction.Left)` — slide in from direction
- `fadeTransition(duration?)` — cross-fade
- `zoomInTransition(area, duration?)` — zoom into a BBox area
- `zoomOutTransition(area, duration?)` — zoom out from a BBox area
- `waitTransition(duration?)` — wait without visual transition

**Directions:** Top, Bottom, Left, Right, TopLeft, TopRight, BottomLeft, BottomRight

**Custom:**
```ts
import {useTransition} from '@motion-canvas/core';
const transition = useTransition(ctx => { /* current */ }, ctx => { /* previous */ });
yield* transition(1);
```

## Advanced Patterns

**Conditional:** `if (cond()) yield* a(); else yield* b();`
**Reactive:** ` val() > 150 ? 'red' : 'blue'} />`
**State machines:** `while/switch` pattern with enum states

## References

- [Setup](references/SETUP.md) — Project creation, installation, troubleshooting
- [Flow Control](references/FLOW_CONTROL.md) — all, any, chain, delay, sequence, loop
- [Tweening](references/TWEENING.md) — Property tweens, easing, interpolation
- [Springs](references/SPRINGS.md) — Physics-based spring animations
- [Transforms](references/TRANSFORMS.md) — Coordinates, positioning, matrix operations
- [Presentation Mode](references/PRESENTATION_MODE.md) — Slide-based playback
- [Txt](references/TXT.md) — Text rendering, dynamic text, multi-line
- [Layout](references/LAYOUT.md) — Flexbox, cardinal directions, offset
- [LaTeX](references/LATEX.md) — Mathematical equations
- [Media](references/MEDIA.md) — Images, icons, video
- [SVG](references/SVG.md) — Animatable SVG component
- [Icons](references/ICONS.md) — Iconify icon usage and catalog
- [Camera](references/CAMERA.md) — Pan, zoom, follow
- [Filters](references/FILTERS.md) — blur, brightness, contrast, grayscale, sepia, hue, saturate, invert
- [Gradients](references/GRADIENTS.md) — Linear, radial, conic gradient fills
- [Effects](references/EFFECTS.md) — createEffect, createDeferredEffect
- [Rendering](references/RENDERING.md) — Rendering settings and output configuration
- [Sounds](references/SOUNDS.md) — Programmable sound playback (@alpha)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [VideoZero](https://github.com/VideoZero)
- **Source:** [VideoZero/skills](https://github.com/VideoZero/skills)
- **License:** Apache-2.0
- **Homepage:** https://videozero.ai

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-videozero-skills-motion-canvas
- Seller: https://agentstack.voostack.com/s/videozero
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
