| name | mira-svg-morph |
| description | Gera num slide do Mira (novo ou existente) uma forma SVG que morfa em outra(s) em loop contínuo, com GSAP e MorphSVGPlugin vendorados localmente (deck offline, file://). O usuário aponta 2 ou mais arquivos .svg da pasta assets/ na ordem do morph; a skill inline os paths com ids únicos, converte formas não-path e monta a timeline em loop. Card limpo, laranja FF904D, herda a Regra Zero e respeita prefers-reduced-motion. Use SEMPRE que o usuário disser /mira-svg-morph, morfa esse svg no outro, uma forma virando outra, morphing de svg, transição de forma, faz um ícone virar outro, ou der dois ou mais SVGs pedindo um virar o outro. Quando o usuário só descreve em palavras, use mira-icon-morph. |
Skill: SVG que morfa em outro, em loop
Gera um slide onde uma silhueta vetorial vira outra diante do espectador, em loop. É o ato visual de uma metáfora: o abstrato vira concreto, ou uma coisa revela a outra. O usuário traz os arquivos .svg; a skill faz o morph.
Fonte da verdade: padrão validado em decks/apresentacao-mira-gsap/ na sessão de 2026-06-19. morph-demo.html (dois SVGs, ida e volta), morph-sequencia.html (vários SVGs encadeados) e o GSAP já vendorado em assets/gsap/. A spec completa está em _reversa_sdd/GSAP/mira-svg-morph-spec.md. Quando em dúvida sobre o scaffold, copie desses arquivos.
Como o morph funciona
O MorphSVGPlugin transforma o atributo d de um <path> no d de outro. Implicações:
- Morfa
<path> em <path>, não "SVG inteiro" em "SVG inteiro". Cada SVG limpo de path único morfa liso. SVG com vários paths morfa par a par (path 1 vira path 1, path 2 vira path 2).
- Multi-path com contagens diferentes: pareie na ordem até o menor número de paths; os paths que sobram entram e saem por fade. Avise a assimetria ao usuário.
- Morfa só a silhueta. Cor, preenchimento e contorno animam à parte (aqui a cor é fixa no laranja Mira por padrão).
- Não morfa raster (
<image>/PNG) nem texto (<text>) sem antes virar path. Se o SVG só tiver isso, avise e peça um contorno vetorial.
- Mesmo viewBox nos dois. Se forem diferentes, normalize para um viewBox comum (escala/translada), senão o morph "salta".
- Formas de complexidade muito diferente podem morfar "líquido". É aceitável; o MorphSVG já faz um mapeamento padrão.
Vendorar o GSAP (offline)
O deck do Mira abre por file://, então nada de CDN em runtime. Baixe os dois arquivos para assets/gsap/ do deck (uma vez por deck; se já existirem, pule):
curl -s https://cdnjs.cloudflare.com/ajax/libs/gsap/3.13.0/gsap.min.js -o assets/gsap/gsap.min.js
curl -s https://cdnjs.cloudflare.com/ajax/libs/gsap/3.13.0/MorphSVGPlugin.min.js -o assets/gsap/MorphSVGPlugin.min.js
GSAP e MorphSVG são gratuitos e redistribuíveis desde abril de 2025 (inclusive comercial), então podem ficar commitados no deck. Referencie por caminho relativo no <head>:
<script src="assets/gsap/gsap.min.js"></script>
<script src="assets/gsap/MorphSVGPlugin.min.js"></script>
Inline + ids únicos + convertToPath (em tempo de geração)
No file:// o fetch de SVG costuma ser bloqueado, então o inline é feito agora, pela skill, não no navegador:
- Ler cada
.svg apontado pelo usuário e extrair o d de cada <path>.
- Renomear ids de paths, gradientes, filtros e clipPaths para valores únicos por arquivo (prefixo por índice, ex.:
m0-, m1-), para não colidir entre vários SVGs no mesmo documento.
- Converter formas que não são path (circle, rect, ellipse, polygon, polyline, line) com
MorphSVGPlugin.convertToPath(...) antes do morph, ou já guardar o d equivalente.
- Guardar os
d como constantes JS (uma por forma), na ordem do morph.
REGRA ZERO (herdada) + acessibilidade
Todo slide do Mira tem loop interno: a timeline do morph usa repeat: -1 e nunca para. Descreva o loop em uma frase ("a nuvem vira lâmpada, vira olho, vira coração e volta, sem parar").
Respeite prefers-reduced-motion: quando ativo, não rode o loop; mostre a forma final estática.
Composição do card (padrão do mira-animator: limpo, forma maximizada)
- Só título + forma. Título no topo, sem ícone, no máximo 6 palavras. A forma ocupa boa parte da altura útil do palco.
- Laranja #FF904D na forma, com glow suave. Fundo escuro do deck.
- Insira como
<section> no padrão do deck e preserve o sistema de navegação (barra de progresso, próximo, teclado).
Scaffold canônico (gerar conforme os arquivos de teste)
A forma morfante é um <path> dentro de um grupo que escala o sistema 0 0 24 24 (caso dos ícones) para o palco. Como o path vive no espaço 24x24 e é escalado, o stdDeviation do glow fica pequeno (~0.7), senão o blur explode.
<div class="anim-stage" id="SLUG-stage"><svg id="SLUG-svg" viewBox="0 0 1280 720" preserveAspectRatio="xMidYMid meet"></svg></div>
gsap.registerPlugin(MorphSVGPlugin);
const REDUCE = matchMedia('(prefers-reduced-motion: reduce)').matches;
const MIRA_SIZE = 3;
const SPEED = 0.7 + MIRA_SIZE * 0.1;
const FORMAS = [
"M6.5 20q-2.28 0-3.89-1.57...Z",
"m12 21.35l-1.45-1.32C5.4...z"
];
function animateSlug() {
const svg = document.getElementById('SLUG-svg');
if (window.__slugTl) window.__slugTl.kill();
const H = 300, s = (H / 24).toFixed(2);
svg.innerHTML = `<defs>
<filter id="SLUG-glow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="0.7" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs>
<g transform="translate(640 330) scale(${s}) translate(-12 -12)">
<path id="SLUG-forma" d="${FORMAS[0]}" fill="#FF904D" filter="url(#SLUG-glow)"/>
</g>`;
if (REDUCE) { document.getElementById('SLUG-forma').setAttribute('d', FORMAS[FORMAS.length - 1]); return; }
const seq = FORMAS.length === 2
? [FORMAS[1], FORMAS[0]]
: FORMAS.slice(1).concat([FORMAS[0]]);
const tl = gsap.timeline({ repeat: -1, defaults: { ease: 'power2.inOut' } });
seq.forEach(d => tl.to('#SLUG-forma', { duration: 1.3, morphSVG: d }, '+=0.7'));
tl.timeScale(SPEED);
window.__slugTl = tl;
}
Registre animateSlug no setupAnimationTriggers() do deck (mesmo padrão do mira-animator): dispara ao entrar na viewport e no botão Replay.
Passos
- Receber destino + arquivos. Slide novo ou slide N do deck X, e os 2+
.svg na ordem do morph. Com 1 só, avise que o morph precisa de 2 ou mais. Se faltar arquivo, pergunte.
- Vendorar o GSAP em
assets/gsap/ (pule se já houver).
- Inline + ids únicos + convertToPath: ler cada SVG, extrair os
d, renomear ids, converter formas não-path. Se as contagens de path diferirem, pareie até o menor e avise; se os viewBox diferirem, normalize e avise.
- Montar o card limpo: título sem ícone (máx. 6 palavras), forma grande e central em #FF904D, marcador
@MIRA:SIZE 3/10. Inserir como <section> no padrão do deck; preservar a navegação.
- Implementar a timeline com o scaffold:
repeat: -1, 2 = ida e volta, N = encadeia; prefers-reduced-motion mostra a forma final estática; registrar no trigger do deck.
- Reportar. Caminho do arquivo, a sequência do morph e o loop em uma frase, os arquivos usados, e que abre por
file:// sem servidor.
Checklist