Skip to content
Back to skills

hand-drawn-film

ASecurity

Make short hand-drawn films in JavaScript and Canvas 2D (pencil, ink, risograph, screen print, brush-pen doodles on photos, sand animation, pop-up paper) and export an MP4 with a synthesized score. Whole-pose drawings authored as SVG path data, exposure sheets, draw-on reveals, boiling holds, and a review loop (onion skins, motion report) that lets you judge animation without watching it. Use for hand-drawn cartoons, animated explainers, sketch-style intros, rotoscope, sand stories or drawing...

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 26, 2026
ai-agentsjavascriptjavabashnodeapi

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 13 files and shows the line behind each finding

Scanned September 26, 2026

npx -y skills add anzal1/hand-drawn-film --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of hand-drawn-film?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for hand-drawn-film
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anzal1-hand-drawn-film/badge)](https://www.skillsdirectory.com/skills/anzal1-hand-drawn-film)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hand-drawn-film
description: >-
  Make short hand-drawn films in JavaScript and Canvas 2D (pencil, ink, risograph, screen print,
  brush-pen doodles on photos, sand animation, pop-up paper) and export an MP4 with a synthesized
  score. Whole-pose drawings authored as SVG path data, exposure sheets, draw-on reveals, boiling
  holds, and a review loop (onion skins, motion report) that lets you judge animation without
  watching it. Use for hand-drawn cartoons, animated explainers, sketch-style intros, rotoscope,
  sand stories or drawings that interact with photos. Not for UI animation or slide decks.
---

# Hand-drawn film

You are making a film that must feel drawn by hand in its marks **and** its movement. You cannot
watch playback, so this skill gives you instruments that turn motion into stills and numbers.
Use them after every change. The loop is the method:

```
draw keys -> render one still -> build the exposure sheet -> onion / strip the hard action
-> review.mjs -> fix -> full render -> review.mjs on the final -> deliver with limitations
```

## 1. Start a project (1 minute)

```bash
node <skill>/scripts/new.mjs ~/films/my-film --ar 16:9 --look pencil --title "My film"
cd ~/films/my-film && npm i --no-audit --no-fund
node render.mjs film.html --grid 24
```

`film.html` is a complete, working starter (a ball hops onto a box) with the canonical structure:
drawings, one exposure sheet, the shot, a score whose cues read the sheet. Keep the structure,
replace the drawings. Fill `brief.md` first; infer routine choices, ask the user only about
decisions that change the film (subject, length, look, format, ending). Needs Node 22+, Chrome,
ffmpeg. For looks other than pencil/ink, or photos, sand and paper, start from the matching
example in `examples/` (table below) and copy its modules locally.

## 2. Draw (the part that decides quality)

Author each key pose as a **whole drawing** in SVG path data with `svgCel` (see
[redrawn-animation.md](references/redrawn-animation.md) and [sketch.md](references/sketch.md)).

- Same stroke names in every key; start each stroke at the same landmark; pass `points: N` so
  `inbetweenCel` matches strokes by arc length. A new view, a closed eye or a changed overlap is
  a **replacement drawing** (`put`), never a morph.
- Give closed forms `fill: 'paper'` so a front shape hides the lines behind it. Stroke order is
  painter's order: background first, near limbs last. Add an invisible silhouette
  (`opacity: 0, fill: 'paper'`) first when a body is built from open strokes.
- Line weight: pencil `weight 1.8-2.2, value 1.3`; ink `weight 1.1-1.3`. Weight is judged at
  thumbnail size, not full size. Target ink contrast 110+ in the review table.
- Render each key alone (`?pose=` pattern in `examples/cat-and-mug.html`) and look at them side by
  side before animating. A texture never rescues an unclear silhouette.
- Composition: subject in the middle 60% of the frame, horizon or table around 60-65% down,
  nothing important within 5% of an edge. Frame with `cam()` rather than moving every drawing.
- **Call `setFormat()` before any file-scope constant reads `W`, `H`, `CX`, `CY`.** `defineFilm()`
  runs last; without this the film is laid out on the 1:1 default (the starter shows the pattern).

## 3. Animate (exposure sheet)

Use `sheetBuilder({library: RAW})`: `key`, `between(a, b, spacing(n, kind), frames)`, `hold`
(optionally `{boil: 3, every: 4}`), `put` for replacements, `mark('name')` for cues. Numbers
that work at 24 fps are in [craft.md](references/craft.md). The short version:

- Moves on twos; fast actions (a swipe, a hit, a fall) on ones; holds 8-24 frames, boiling on
  fours with `keep` for eyes and contacts. Never boil on ones.
- Spacing is the acting: `slowInOut` for most moves, `slowIn` into a landing or a look,
  `slowOut` out of a crouch into a throw or fall, `even` only for machines and ballistics along
  the horizontal.
- Anticipation 4-8 frames before any fast action; a settle after it. Give the viewer about
  one second to read a new idea before the next one starts.
- Props with physics (a falling mug) use formulas on continuous time, not keys. Cue sound from
  marks (`film.time('contact')`) so it cannot drift.

## 4. Look at the motion (every iteration)

```bash
node render.mjs film.html --grid 24          # composition across the film (faithful thumbnails)
node render.mjs film.html --onion 96,16      # one action overlaid blue->red, with a spacing trail
node render.mjs film.html --strip 96,12      # consecutive frames at readable size
node render.mjs film.html --only 96          # one full-size frame for line detail
node review.mjs film.html                    # motion report: pops, flicker, shimmer, blank,
                                             # frozen, faint lines, pacing, exposure per scene
```

Read [review.md](references/review.md) for how to interpret each finding. In an onion, the dots
are the ink centroid per frame: evenly spaced dots are even spacing, bunched dots are a slow in or
out, a straight chain on a jump means the arc is missing. Fix every `warn` or state why it is
intended; confirm each finding by eye with `--strip` around the frame. The numbers are
measurements, not taste.

## 5. Deliver

```bash
node render.mjs film.html                    # frames, mp4, contact sheet, -final.mp4 with score
node review.mjs film.html                    # on the finished film
```

Full renders run on parallel browser processes (`--jobs N`) and are bit-identical to serial
renders. Deliver the source folder, the MP4, the contact sheet, the review report and a short
list of known limitations. Verify duration, dimensions and frame count (ffprobe). Never call a
film finished because code or checks passed; say what you looked at (onions, strips, stills) and
that you did not watch it at speed if you could not.

## Choose references by task

| task | read | start from |
|---|---|---|
| any character in pencil or ink | [redrawn-animation.md](references/redrawn-animation.md), [sketch.md](references/sketch.md), [craft.md](references/craft.md) | `examples/cat-and-mug.html`, `examples/sketchbook-bird.html` |
| timing, spacing, contacts, weather | [motion.md](references/motion.md), [craft.md](references/craft.md) | `examples/weight-study.html` |
| looks: ink, pencil, riso, screen, doodle | [style.md](references/style.md), [palettes.md](references/palettes.md) | `examples/four-looks.html` |
| several looks in one film | [mixed-media.md](references/mixed-media.md) | `examples/becoming-phoenix/` |
| drawings on real photos | [doodle.md](references/doodle.md) | `examples/held-once.html`, `examples/night-shift.html` |
| traced real motion | [found-motion.md](references/found-motion.md) | `examples/gallop.html` |
| sand animation | [sand.md](references/sand.md) | `examples/one-year.html` |
| pop-up paper in 3D | [paper3d.md](references/paper3d.md) | `examples/moon-book.html` |
| engine APIs, export, pitfalls | [architecture.md](references/architecture.md), [studio.md](references/studio.md) | |
| reading review output | [review.md](references/review.md) | |

[scenes.md](references/scenes.md) and [reference-films.md](references/reference-films.md) hold
optional scene devices and historical references, not required structures.

## Invariants

- 24 fps by default. Scenes get continuous `tau`; quantize a pose once (`twos(t)` or an exposure
  sheet), never twice. Camera and physics usually run on ones.
- No output-frame seeds. A held drawing holds its marks; a boil is a finite set of drawings.
  Every frame must reproduce after seeking (render workers depend on it).
- Contacts stay planted until their planned release; IK clamps and reports unreachable targets.
- Record sources and licences for external media (photos, fonts).
- Engine edits belong in the skill's `assets/`, then get copied to films; do not fork `core.js`
  inside one film.

## Quality gates

- **Drawing:** clear silhouette at 240 px; consistent proportions across keys; line hierarchy
  (outer contour heavier than interior detail); purposeful taper and gaps; no accidental
  tangents; front forms hide what is behind them.
- **Motion:** readable keys, anticipation and settle where the action needs them, deliberate
  spacing (check the onion), planted contacts, no pops or two-drawing flicker in the review.
- **Material:** texture tied to the paper or object, not the screen; no shimmer unless intended;
  line contrast 110+ at thumbnail size for line films.
- **Delivery:** no page errors, no unintended blank frames, the ending holds 0.5-1.5 s, text and
  cards stay up long enough to read (about 3 words per second plus one second), the encoded MP4
  decodes and has the expected frame count.

`node scripts/verify.mjs` runs the engine's regression suite (20 checks) after engine edits.

Files in this skill

  • SKILL.md8.6 KB
  • assets/cels.js6.7 KB
  • assets/core.js86.4 KB
  • assets/film-template.html12.1 KB
  • assets/materials.js3 KB
  • assets/paper3d.js16.9 KB
  • assets/preview-cat-and-mug.jpg61 KB
  • assets/preview-fly-style.jpg87.5 KB
  • assets/preview-template.jpg62.1 KB
  • assets/preview-weight-study.png73.5 KB
  • assets/roto.js4.9 KB
  • assets/sand.js25 KB
  • assets/sketch.js15.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…