Animação em line art
Componentes de ilustração animada: tudo é desenhado com uma única caneta fina sobre papel, construído ao vivo em SVG a partir de TypeScript, mantendo-se nítido em qualquer tamanho, respondendo ao ponteiro e podendo ser avançado quadro a quadro para verificação ou exportação de vídeo.
Este skill fornece uma pequena biblioteca (lib/), dois exemplos (examples/walker, uma única
figura em ~150 linhas; examples/village, uma cena completa) e ferramentas (scripts/).
Leia o exemplo mais próximo do pedido antes de escrever qualquer código.
Como as pessoas julgam este trabalho
Elas olham como um animador olharia: quadro a quadro, com zoom, comparando com a vida ou com uma referência. Todos estes foram rejeitados na prática, e cada um tem uma regra abaixo:
- caminhadas que balançam em uma senoide, pés que deslizam, passos acelerados para caber em um time-lapse
- membros desenhados como tubos fechados; linhas retas de régua; roupas rígidas que ignoram as pernas
- um conjunto inteiro de componentes construídos de uma vez que parecem todos iguais ("IA genérica")
- interações que parecem UI em vez de o mundo reagir
- uma página cujo fundo muda com a cena ("parece vídeo, não componente")
- reutilizar personagens de um clipe de referência quando foi pedido algo novo
- adereços sobrando que ninguém pediu (pediram para remover a roupa no varal)
Fluxo de trabalho
- Fixar a aparência antes de qualquer movimento. Leia
references/style.md. Decida a espessura da caneta, cor do papel, proporções da figura e uma ou duas cores de destaque planas. - Configurar o projeto. Copie
lib/para o projeto (são quatro arquivos.tssem dependências) e use Vite + TypeScript (package.json,tsconfig.jsonevite.config.tsneste repositório mostram a configuração). Os componentes são DOM/SVG puro — nenhum framework necessário. - Construa uma figura ou um canto primeiro e mostre (captura de tela ou um clipe curto, junto com a referência, se houver). Obtenha um sim antes de construir o resto. Um conjunto completo construído de uma vez volta como genérico; uma peça boa mostra o padrão.
- Faça-o se mover com
references/motion.md:gait()para andar e correr,spring()/pendulum()para qualquer coisa presa ou pendurada, poses chaveadas comcurve()ousequence()para gestos. Nunca anime uma figura com senoides livres. - Componha a cena com
references/scenes.md: um cartão autossuficiente em um fundo de página fixo, camadas, uma paleta de hora do dia delib/daynight.ts, luzes, vento, pessoas chegando em horários, interações que são reações. - Verifique com
references/verify.mdantes de mostrar qualquer coisa: typecheck, avanço com?debug, tiras de quadro com zoom de tudo que se move, interações acionadas e percorridas, 60 fps em uma aba real. - Se houver um clipe de referência para igualar, siga
references/matching.md— meça o tempo e as poses do clipe em vez de adivinhar, e confira com uma sobreposição. - Se quiserem um vídeo, siga
references/video.md(captura headless determinística comscripts/capture.ts, depois ffmpeg).
Regras que fazem funcionar
- Membros são dois traços abertos.
limb()desenha uma banda preenchida com papel entre duas linhas de caneta que param antes de se encontrar na extremidade oposta. Esta é a marca registrada do estilo. - Linhas são curvas. Junções são arredondadas, bordas curvam levemente, nada é reto de régua.
- Desenhe cada figura em seu próprio espaço — ~95 unidades de altura, pés em y = 120, voltada para +x,
parada em x = 40 — e posicione-a com
place(g, x, y, dir, escala). Proporções, espessura da caneta e os presets de marcha assumem este espaço. - Roupas são desenhadas ao redor do esqueleto. Resolva as pernas (mesmo que ocultas), depois desenhe a barra do casaco ou quimono a partir do joelho da frente e dos tornozelos, para que o tecido abra e feche com a passada. Mangas, cachecóis e bolsas balançam em molas.
- Pés estão plantados. Mova um andarilho exatamente
gait.speed × escalapor segundo e o pé de apoio fica parado no chão. Não acelere uma marcha para caber em um relógio comprimido; comprima as chegadas. - Tinta é
currentColor, papel é.pp. Retinte todo o desenho comapplyPalette()(dia: tinta escura em papel quente; noite: tinta clara em índigo, janelas quentes). Preenchimentos de membros com cor sólida devem usarsolid(), senão o CSS do papel vence. - O componente é um cartão. A página ao redor nunca muda de cor.
- Interações são o mundo reagindo: uma pessoa faz uma reverência ou toca o chapéu, um gato acorda e se espreguiça, um lampião balança, pássaros se dispersam, um peixe pula. Movimento do ponteiro é vento. Sem botões dentro da cena; uma única linha de dica sutil é suficiente.
- Novo significa novo. Se o briefing é "como este, mas novo", mantenha o meio, a caneta, as proporções e a sensação de tempo; invente os personagens, atividades e adereços.
Biblioteca de relance
| módulo | o que oferece |
|---|---|
lib/ink.ts | pen shape blot paint limb solid joint hang curve shoe place toScene inkDefs run |
lib/gait.ts | `gait({ kind: 'walk' |
lib/motion.ts | spring pendulum pointerWind sequence seeded wobble ease minJerk … |
lib/daynight.ts | palette(τ) → sky, paper, ink, lamp, night, sunset; applyPalette nightTint |
run(draw) controla tudo com draw(t, dt). Duas flags de URL importam para verificação:
?t=1.25 congela o tempo; ?debug desativa o rAF e expõe window.__step(seconds)
para avanço exato (abas em segundo plano e headless limitam o rAF, então sempre verifique no modo debug).
Scripts
scripts/capture.ts <url?debug> <outDir> <frames> <fps> [w] [h] [setupJs] [frameJs]— quadros PNG determinísticos a partir de Chrome headlessscripts/clip.ts period|blobs …— comprimento de loop de uma região; rastreamento de blob escuro por quadroscripts/frames.sh <clip> x y w h outDir— quadros com grade sobreposta para ler poses de um clipe
Todos executam com Node ≥ 22.18 (TypeScript é removido nativamente) mais ffmpeg; capture.ts
localiza um Chrome/Chromium local ou usa $CHROME.