CommunityImagemgithub.com

handdrawn-3d

Versão 3D do handdrawn. Desenhe um objeto, animal, planta, comida ou cena pequena como um modelo 3D renderizado com aparência de desenho à mão (caneta e marcador) e entregue como um SVG animado em loop, mais um PNG estático ou GIF.

O que é handdrawn-3d?

Esta skill cria modelos 3D de objetos do mundo real com aparência de desenho à mão (tinta e marcador), gerando um SVG animado em loop onde algo no objeto se move (tampa que vibra, pão que pula, hélices que giram, vapor que sobe). O resultado é um arquivo SVG autocontido, sem JavaScript, que funciona em navegadores e tags `<img>`. A skill também exporta PNG estático e, opcionalmente, GIF. O processo envolve modelar o objeto com sólidos simples (cilindros, caixas, tubos), animar usando funções como `k.wave()` e `k.pulse()`, e renderizar com uma ferramenta de linha de comando. A skill é adequada para desenhos 3D, isométricos ou modelados; para desenhos comuns deve-se usar a skill 2D. Não deve ser usada para diagramas, gráficos, UI ou páginas interativas. Suporta texto com fonte desenhada à mão e tem suporte completo a vietnamita.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/duy211099/handdrawn-skill/tree/HEAD/handdrawn-3d

Installed? Explore more Imagem skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que handdrawn-3d faz?

Você modela o assunto em 3D com alguns sólidos simples, e o kit o desenha à mão. As faces recebem três tons planos de marcador a partir de uma luz no canto superior esquerdo. Faces vizinhas do mesmo tom se fundem em uma mancha. O contorno é traçado com tinta pesada e as dobras mais leves, com linhas trêmulas e afiladas, sobre papel creme. A cena é desenhada uma vez por quadro com t percorrendo um loop. A saída é um SVG animado em loop: os quadros são alternados por CSS, sem script, funcionando em navegadores e tags <img>. O texto usa uma fonte desenhada à mão integrada com suporte completo a vietnamita.

Kit: assets/kit.js · renderizador: assets/render.mjs · todas as funções e opções: references/kit.md (leia antes de escrever uma cena) · exemplos práticos: examples/ (xícara, bule, torradeira, moinho: leia o mais próximo).

Configuração (uma vez)

A exportação de PNG/GIF precisa de @resvg/resvg-js. Se render.mjs disser que está faltando, execute npm install na pasta desta skill. O SVG em si não precisa de nada.

Antes de desenhar

  • É desenhável? Se o assunto for abstrato ("esperança", "produtividade"), não desenhe algo vago. Sugira uma ou duas cenas concretas que o representem e desenhe a que o usuário escolher.
  • Diagramas, gráficos, UI, botões, coisas interativas: não é para esta skill.
  • O que se mexe? Cada imagem anima o próprio objeto: a câmera nunca se move. Escolha um ou dois movimentos que pertençam ao assunto. A tampa de uma chaleira vibra e solta vapor. Torrada pula. As hélices de um moinho giram. Um ventilador gira. O rabo de um gato balança. Um lampião acena. Uma planta balança. Se o usuário nomear um movimento, use esse. Se nada puder se mover de forma plausível, use vapor, um balanço suave ou um sway, e a agitação natural das linhas.

Fluxo de trabalho

  1. Partes. Liste as partes reais do assunto e como cada uma é construída a partir de sólidos. Escreva numa tabela como comentário no topo da cena: parte · chamada · tamanho/posição · cor. Modele a partir das partes reais (aros, tampas, botões, alças, pés, fendas, dobradiças), não um bloco único com um nome. Consulte proporções que não tem certeza.
  2. Modele em scene.js (mundo: x direita, y trás, z cima, chão z = 0; unidades em mm; enquadramento automático):
    • coisas redondas que daria para tornear → k.lathe (recipientes usam wall:), k.cylinder, k.sphere
    • coisas cúbicas → k.box (round: para cantos arredondados de eletrodomésticos), contornos irregulares → k.extrude
    • alças, bicos, tubos, pernas, cabos, hastes → k.tube, começando dentro do corpo (é cortado na superfície)
    • conteúdo de um recipiente → { in: container }; marcas planas numa face → k.panel / k.line com { on: solid }
    • gire o assunto inteiro com k.group({ rotate: { z: 45 } }, …) quando a "vista lateral" deve ficar voltada para o observador (bico do bule à esquerda e alça à direita)
  3. Anime com t ∈ [0, 1): partes móveis vão dentro de um k.group({ about, rotate, at }, …) acionado por k.wave(), k.pulse() ou 360 * t. Cada movimento deve retornar à posição inicial em t = 1.
  4. Renderize e veja:
    node <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png --strip --thumb
    
    Abra out/scene.png (um quadro estático) e out/scene-frames.png (6 quadros ao longo do loop) com a ferramenta Leitura e observe-os. Adicione --grid para ler coordenadas da folha. Verifique out/scene-128.png: ainda deve ser reconhecível como o assunto em 128 px.
  5. Corrija e renderize novamente. Verifique:
    • É reconhecível como o assunto à primeira vista? Silhueta primeiro.
    • Nada desenhado na ordem errada: uma parte aparecendo através do corpo, uma parte distante sobre uma próxima, conteúdo escondido ou furando. Corrija com as regras em Como os sólidos são ordenados em references/kit.md: sólidos separados, in:, on:, modele apenas o que sai de uma abertura, e layer como último recurso.
    • As partes tocam o que as segura. Nada flutua a menos que deva (uma tampa saltando).
    • O movimento é legível na tira de quadros e faz loop sem salto.
    • Rótulos ficam nas margens e não cruzam o desenho mais do que o necessário. Repita 4–5 até ficar certo (geralmente 2–4 rodadas). Renderize a versão final sem --grid.

Nunca entregue sem ter visto o quadro estático e a tira de quadros. Entregue o caminho do SVG (a imagem animada), mais o PNG, e mostre o PNG. Adicione --gif out/scene.gif quando o usuário quiser um GIF ou o SVG tiver que ir para algum lugar que não reproduza animação SVG (apps de chat, alguns clientes de email).

Regras de estilo

  • Um visual: tinta + tons planos de marcador sobre papel. Sem gradientes, brilhos, desfoque, truques de opacidade, SVG <text> ou SVG bruto. Use apenas o kit.
  • Cor: nomes de paletas (veja references/kit.md), 3–5 por imagem mais tinta. Nomes de paletas ficam melhores; qualquer hex é suavizado. Tons claro, médio e escuro vêm automaticamente de cada preenchimento. Não simule sombreamento com sólidos extras.
  • Câmera: isométrica por padrão. Altere sheet.camera apenas por um motivo. Uma inclinação mais baixa (20–25) e um ângulo horizontal de 25–35 produzem um "product shot" mais amigável para coisas altas (torres, garrafas, luminárias, pessoas).
  • Simples e encorpado: poucos sólidos limpos funcionam melhor que muitos detalhados. Peças pequenas (botões, pés, interruptores) são o que tornam real: adicione-as.
  • Chão: sombras são automáticas. Algo apoiado sobre uma tábua, mesa ou pires projeta sua sombra sobre ele. Uma tábua, bandeja, montículo ou mesa sob um objeto pequeno ajuda a situá-lo no espaço.
  • Texto: opcional k.title(...) no canto superior esquerdo, mais notas curtas em minúsculas nas margens (k.label) apontando para pontos 3D. Escreva-as no idioma do usuário. Sem caixas ou balões de fala sobre o desenho.
  • Folha: 1000×1000 por padrão. Para cenas amplas use export const sheet = { width: 1200, height: 900 }. --transparent remove o papel.
  • Tamanho da animação: 16 quadros a 12 fps (loop de 1,3 s) por padrão; um SVG típico tem 0,5–1 MB. Para movimento lento use sheet.fps = 8. Mantenha frames ≤ 24.

Template de cena

// Um bule sobre um tripé; a tampa vibra.
// parte      chamada               tamanho / posição                    cor
// tripé      cylinder              r 120, h 10                          madeira
// corpo      lathe { smooth }      r 55→94→50, h 118, sobre o tripé    verde-azulado
// bico       tube [14, 7]          de dentro do corpo, para a esquerda verde-azulado
// alça       tube 8                ambas as pontas dentro do corpo, direita  verde-azulado
// tampa+botão lathe + esfera       em um grupo articulado na borda traseira verde-azulado, ocre
export const sheet = { seed: 3 };
export function draw(k, t = 0) {
  k.cylinder([0, 0, 0], 120, 10, { fill: 'madeira' });
  k.group({ rotate: { z: 45 } }, () => {                          // bico à esquerda, alça à direita
    k.lathe([0, 0, 10], [[55, 0], [78, 10], [94, 45], [90, 85], [68, 112], [50, 118]], { fill: 'verde-azulado', smooth: true });
    k.tube([[-78, 0, 50], [-112, 0, 66], [-128, 0, 100], [-146, 0, 118]], [14, 7], { fill: 'verde-azulado' });
    k.tube([[70, 0, 112], [112, 0, 108], [122, 0, 72], [84, 0, 40]], 8, { fill: 'verde-azulado' });
    const pulo = Math.max(0, k.wave(0, 2 * t));                  // 0..1, dois pulos por loop
    k.group({ about: [44, 0, 128], rotate: { y: -18 * pulo }, at: [0, 0, 16 * pulo] }, () => {
      k.lathe([0, 0, 127], [[52, 0], [50, 5], [30, 13], [8, 18], [0, 19]], { fill: 'verde-azulado', smooth: true });
      k.sphere([0, 0, 152], 10, { fill: 'ocre' });
    });
    k.steam([-150, 0, 125], { h: 90, n: 2, spread: 18 });
  });
  k.label('tampa vibrando', { to: [0, 0, 140], side: 'right' });
}

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Habilidades Relacionadas