🎞️ Visão geral — Padrões de composição temporal
A categoria "Animação de Conteúdo" agrupa templates que vão além de animar um único elemento — eles orquestram múltiplos elementos no tempo. O padrão central é o stagger via Sequence com from escalado, mas a categoria também cobre 3D CSS, simulação física e loops perpétuos.
🎯 Os 4 padrões desta categoria
animated-list, notification-pop, progress-steps — vários elementos com from escalado.
card-flip, rotating-carousel — perspective + rotateY para profundidade.
countdown-timer — o número exibido é calculado diretamente do frame, sem useState.
particle-explosion, sound-wave — posição/altura calculada com aritmética por frame.
📋 animated-list — stagger de itens
O animated-list.tsx é o template de referência para stagger de múltiplos elementos. Cada item de uma lista entra com um atraso proporcional ao índice, criando aquela sensação de "os itens vão chegando" que é onipresente em explainer videos e slides animados.
const DELAY_PER_ITEM = 10; // frames entre cada item {items.map((item, i) => ( <Sequence key={i} from={i * DELAY_PER_ITEM}> <ListItem item={item} /> </Sequence> ))} // Dentro de ListItem: frame é LOCAL (começa em 0) const frame = useCurrentFrame(); // 0, 1, 2... const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" }); const y = interpolate(frame, [0, 15], [20, 0], { extrapolateRight: "clamp" });
📊 O poder do frame LOCAL dentro da Sequence
Quando você usa <Sequence from={i * 10}>, o componente filho recebe useCurrentFrame() começando em 0 quando a sequência inicia. Isso significa que cada ListItem pode ter a mesma lógica de animação — não precisa subtrair o offset manualmente. O Remotion cuida do deslocamento.
✓ Certo: Sequence + frame local
<Sequence from={i * 10}> <Item /> // frame começa em 0 </Sequence>
Cada Item tem lógica igual — limpo e reutilizável.
✗ Errado: subtrair offset manualmente
const localFrame = frame - i * 10; if (localFrame < 0) return null;
Verboso, propenso a bugs de borda (frame negativo).
🃏 card-flip — CSS 3D no Remotion
O card-flip.tsx demonstra como implementar 3D CSS dentro do Remotion: duas faces de um card posicionadas com backfaceVisibility: "hidden", o contêiner com perspective, e a rotação interpolada de 0° a 180°.
const frame = useCurrentFrame(); const rotation = interpolate( frame, [15, 45], [0, 180], { extrapolateRight: "clamp" } ); return ( {/* Contêiner: define a perspectiva */} <div style={{ perspective: 800, transformStyle: "preserve-3d" }}> {/* Frente */} <div style={{ backfaceVisibility: "hidden", transform: `rotateY(${rotation}deg)`, position: "absolute", inset: 0 }}>Face A</div> {/* Verso — começa já virado 180° */} <div style={{ backfaceVisibility: "hidden", transform: `rotateY(${rotation - 180}deg)`, position: "absolute", inset: 0 }}>Face B</div> </div> );
💡 Por que backfaceVisibility: "hidden"?
Sem essa propriedade, você veria as duas faces ao mesmo tempo — a frente aparecer espelhada atrás e vice-versa. Com hidden, cada face só é visível quando está "de frente" para o observador. É o segredo de qualquer flip card.
⏳ countdown-timer — estado derivado do frame
O countdown-timer.tsx ilustra um conceito central do Remotion: o valor exibido é sempre uma função direta do frame, sem useState, sem efeitos. O número exibido é calculado a partir do frame atual e dos parâmetros de duração/fps.
const frame = useCurrentFrame(); const { fps, durationInFrames } = useVideoConfig(); // segundos restantes — derivados do frame const secondsLeft = Math.ceil( (durationInFrames - frame) / fps ); // "GO" quando chega a 0 const label = secondsLeft > 0 ? String(secondsLeft) : "GO!"; // spring de entrada para cada mudança de número const frameInSegment = frame % fps; // 0→fps a cada segundo const scale = spring({ fps, frame: frameInSegment, config: { damping: 10, stiffness: 150 } });
Sequência de eventos no countdown (30fps, 5s):
Frame 0 — exibe "5"
(150 - 0) / 30 = 5 → Math.ceil(5) = 5. Spring entra com scale-pop.
Frame 30 — troca para "4"
(150 - 30) / 30 = 4 → número muda, spring reinicia (frame % fps = 0).
Frame 150 — exibe "GO!"
secondsLeft ≤ 0 → label = "GO!". Sem estado, sem setInterval.
💥 particle-explosion — física 2D determinística
O particle-explosion.tsx simula uma explosão de partículas com trajetória física: posição inicial no centro, velocidade com ângulo aleatório (semeado) e gravidade simples. Tudo calculado frame a frame — sem estado acumulado.
const PARTICLE_COUNT = 40; {Array.from({ length: PARTICLE_COUNT }, (_, i) => { // velocidade e ângulo DETERMINÍSTICOS const angle = random(`angle-${i}`) * 2 * Math.PI; const speed = random(`speed-${i}`) * 8 + 2; const vx = Math.cos(angle) * speed; const vy = Math.sin(angle) * speed; // posição frame-a-frame com gravidade const x = cx + vx * frame; const y = cy + vy * frame + 0.15 * frame * frame; // g const opacity = interpolate(frame, [20, 45], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); })}
⚠️ Sem random() semeado = vídeo corrompido
Se você usar Math.random() aqui, cada frame calculado produz uma trajetória diferente — no render paralelo do Remotion, as partículas "pulam" para posições aleatórias. O vídeo final parece corrompido. random("seed") garante que frame 42 sempre tem as mesmas partículas no mesmo lugar.
🎵 sound-wave & text-highlight — loops e foco
Dois templates que demonstram padrões complementares: sound-wave.tsx cria um visualizador de áudio (barras que oscilam com Math.sin) e text-highlight.tsx destaca uma palavra por vez em sincro com o frame — como karaokê ou leitura guiada.
sound-wave
{bars.map((_, i) => {
const h = Math.sin(
frame / 8 // velocidade
+ i * 0.4 // fase
) * 0.5 + 0.5; // 0 a 1
return <rect height={h * maxH}/>;
})}
text-highlight
const words = text.split(" "); const framesPerWord = fps / 2; const activeIndex = Math.floor( frame / framesPerWord ); {words.map((w, i) => ( <span style={{ color: i === activeIndex ? "#60a5fa" : "white" }}>{w}</span> ))}
💡 text-highlight: sincronizar com áudio
O mesmo padrão de Math.floor(frame / framesPerWord) pode ser adaptado para sincronizar palavras com timestamps de transcrição. Nos módulos avançados da T3, você verá como combinar esse template com @remotion/captions para karaokê automático.
📚 Biblioteca Completa — Animação de Conteúdo
📌 Resumo do módulo
Próximo módulo:
2.4 — Imagem & Mídia: galerias, sliders, comparadores e molduras para fotos em vídeo.