MÓDULO 2.1

✍️ Animações de Texto

9 templates, 9 maneiras diferentes de texto se mover. De revelar letra a letra com stagger até onda senoidal e glitch RGB — cada template ensina um padrão que se repete em dezenas de situações reais.

9
Templates
40
Minutos
Inter
Nível
Prático
Tipo
string "REMOTION" R E M O T I +0 +3 +6 +9 +12 +15 delay = i × 3 frames (stagger) REMOTION reveal char-a-char vídeo animado
1

✍️ Visão Geral — A categoria Texto

Texto animado não é opcional em vídeo — é o veículo principal de informação. A categoria Texto da biblioteca cobre 9 padrões distintos, de revelar letra a letra até onda senoidal e glitch RGB. Entender qual usar em qual contexto é o que separa um vídeo raso de um com identidade visual.

🎯 Quando usar animação de texto

Revelar informação progressivamente:

  • animated-text ou typewriter para dados que "chegam"
  • slide-text para entradas direcionais (slide-in)

Chamar atenção sobre texto existente:

  • pulsing-text para respiração suave contínua
  • glitch-text para estilo retro/hacker

✓ Quando o texto anima bem

  • Ritmo alinhado com narração ou música de fundo.
  • Duração proporcional ao comprimento do texto.
  • Estilo de animação coerente com o tom do vídeo.

✗ Quando prejudica

  • Animação mais rápida que a leitura — texto some antes de ser lido.
  • Glitch ou bounce em contexto corporativo sério.
  • Múltiplas animações diferentes na mesma cena.
9 templates
Categoria Texto
3 famílias
Stagger / Física / Efeito
Hook base
interpolate + spring
Padrão
Split → stagger → animate
2

🔤 animated-text — stagger letra a letra

O template animated-text.tsx divide o texto em um array de caracteres e aplica uma Sequence com from escalado por índice. Cada letra entra com um pequeno atraso em relação à anterior, criando o efeito de "digitação veloz" sem usar setTimeout ou estado.

animated-text.tsx — núcleo do stagger templates/animated-text.tsx
const frame = useCurrentFrame();
const chars = text.split("");

return (
  <div style={{ display: "flex" }}>
    {chars.map((char, i) => {
      const opacity = interpolate(
        frame,
        [i * 2, i * 2 + 8],
        [0, 1],
        { extrapolateRight: "clamp" }
      );
      return <span key={i} style={{ opacity }}>{char}</span>;
    })}
  </div>
);

💡 Por que i * 2 e não um valor fixo?

O i * 2 é o delay: cada letra começa 2 frames depois da anterior. Mude para i * 4 e a revelação fica mais lenta; i * 1 deixa quase simultâneo. O + 8 define a duração do fade individual — tempo para opacidade ir de 0 a 1.

Timeline de execução (texto "OLÁ"):

F0

Frame 0 — "O" começa a aparecer

opacity do "O" vai de 0→1 nos frames 0-8. "L" e "Á" ainda invisíveis (opacity=0).

F2

Frame 2 — "L" começa seu fade

"O" ainda animando; "L" inicia interpolação 0→1 nos frames 2-10.

F8

Frame 8 — texto completo visível

Todos os caracteres em opacity=1. Animação concluída.

Padrão
split + map + interpolate
Stagger
i × delay
Extrapolate
clamp (obrigatório)
Reutiliza em
Palavras, linhas, listas
3

🏀 bounce-text — spring com overshoot

O bounce-text.tsx usa spring() em vez de interpolate(). A diferença visual é enorme: em vez de subir linearmente, o texto "quica" — ultrapassa o destino e volta, como um objeto com massa e amortecimento.

bounce-text — spring com parâmetros templates/bounce-text.tsx
const { fps } = useVideoConfig();
const frame = useCurrentFrame();

const scale = spring({
  fps,
  frame,
  config: {
    damping: 8,     // baixo = mais quique
    stiffness: 120, // alto = mais rápido
    mass: 1,
  },
});

return <div style={{ transform: `scale(${scale})` }}>{text}</div>;

✓ Spring: quando usar

  • Títulos hero que precisam de impacto visual.
  • CTAs e botões que "chamam" o espectador.
  • Emojis e ícones expressivos.

✗ Interpolate: quando usar

  • Fades — spring não controla opacidade com precisão.
  • Movimento horizontal exato (slide preciso).
  • Qualquer timing que não pode ter overshoot.

📊 Tabela de parâmetros spring

ParâmetroValor baixoValor alto
dampingelástico, oscila muitofirma rápido, sem bounce
stiffnesslento, preguiçosorápido, agressivo
massleve, rápidopesado, inércia grande
Retorna
0 → ~1 (com overshoot)
Usa fps
sempre passar fps
Combinar
× scale ou translateY
Stagger
frame - i * delay
4

💻 glitch-text — RGB split sem biblioteca

O efeito glitch é obtido com três cópias do mesmo texto sobrepostas, cada uma colorida em um canal (vermelho, verde, azul) e deslocada horizontalmente de forma irregular. Tudo com random() semeado e interpolate multi-keyframe para os pulsos.

glitch-text — RGB split templates/glitch-text.tsx
// deslocamento pulsante para canal vermelho
const glitchX = interpolate(
  frame % 12,                    // pulso periódico
  [0, 2, 4, 6, 12],
  [0, -4, 3, -2, 0],
  { extrapolateRight: "clamp" }
);

return (
  <div style={{ position: "relative" }}>
    {/* cópia vermelha */}
    <span style={{ color:"red", position:"absolute",
      transform:`translateX(${glitchX}px)`,
      mixBlendMode: "screen" }}>{text}</span>
    {/* cópia ciano e texto original */}
  </div>
);

💡 mix-blend-mode: screen

Com mixBlendMode: "screen", onde vermelho e ciano se sobrepõem produzem branco — criando o artefato visual característico do glitch de CRT. Sem o blend mode, as cores simplesmente se cobrem.

⚠️ Não use Math.random() aqui

O deslocamento do glitch precisa ser determinístico — use random("glitch-r") do Remotion para as amplitudes fixas por canal. Math.random() fará o glitch piscar diferente em cada render, quebrando o vídeo no render paralelo.

Técnica
3 cópias sobrepostas
Blend
mixBlendMode: screen
Pulso
frame % período
Seed
random() determinístico
5

🌊 floating-bubble-text — onda senoidal

Em vez de interpolate ou spring, o floating-bubble-text.tsx usa diretamente Math.sin() com o frame como argumento. Cada caractere oscila com uma diferença de fase em relação ao anterior, criando uma onda que percorre o texto continuamente — sem começo nem fim.

onda senoidal por caractere templates/floating-bubble-text.tsx
const frame = useCurrentFrame();

{text.split("").map((char, i) => {
  const y = Math.sin(
    frame / 12       // velocidade da onda
    + i * 0.5     // fase por índice
  ) * 8;           // amplitude em px

  return (
    <span key={i} style={{ display:"inline-block",
      transform: `translateY(${y}px)` }}>
      {char}
    </span>
  );
})}

📊 Ajustando o comportamento

frame / 12 — velocidade: número maior = mais lento
i * 0.5 — defasagem: menor = mais sincrônico
* 8 — amplitude: pixels de deslocamento vertical
Técnica
Math.sin(frame)
Loop
Periódico automático
Fase
i × offset
Uso
Backgrounds e decoração
6

⌨️ typewriter-subtitle — cursor piscante

O typewriter-subtitle.tsx emula uma digitação real: mostra progressivamente mais caracteres do texto usando text.slice(0, visibleChars), onde visibleChars deriva diretamente do frame. O cursor pisca com interpolate multi-keyframe.

typewriter + cursor piscante templates/typewriter-subtitle.tsx
const frame = useCurrentFrame();
const charsPerFrame = 0.3; // velocidade de digitação

const visibleChars = Math.floor(frame * charsPerFrame);
const displayText = text.slice(0, visibleChars);

// cursor pisca a cada ~15 frames
const cursorOpacity = interpolate(
  frame % 20,
  [0, 10, 20],
  [1, 0, 1]
);

💡 Ajustando a velocidade

charsPerFrame = 0.3 digita ~9 chars/seg a 30fps. Para digitar mais rápido: aumente para 0.5. Para lento, tipo terminal: 0.15. A fórmula Math.floor(frame * rate) é o padrão universal para "quantos elementos mostrar até agora".

Técnica
slice(0, frame×rate)
Cursor
frame % período
Velocidade
charsPerFrame
Uso
Legendas, código, tutoriais
7

📚 Biblioteca Completa — Categoria Texto

Todos os 9 templates da categoria, com arquivo, descrição em uma linha e hook principal utilizado.

TemplateDescriçãoHook principal
animated-text.tsx Reveal char a char com stagger interpolate
bounce-text.tsx Entrada com overshoot elástico spring
bubble-pop-text.tsx Scale 0→1.2→1 por palavra spring
floating-bubble-text.tsx Onda senoidal por caractere Math.sin
glitch-text.tsx RGB split com pulso irregular interpolate + random
popping-text.tsx Scale pop por palavra independente spring stagger
pulsing-text.tsx Respiração contínua de opacidade Math.sin loop
slide-text.tsx Slide direcional com easing out interpolate + easing
typewriter-subtitle.tsx Digitação com cursor piscante slice + frame%

📌 Resumo do módulo

Stagger = split + map + i × delay — o padrão universal para revelar elementos em sequência.
spring para pop orgânico — damping baixo = bounce, damping alto = firme.
Math.sin(frame) para loops perpétuos — onda, respiração e qualquer movimento cíclico.
Glitch = 3 cópias + mixBlendMode — efeito visual complexo sem biblioteca externa.
random() semeado — aleatoriedade visual sem quebrar o render determinístico.

Próximo módulo:

2.2 — Charts & Dados: SVG animado com interpolate, dashoffset, arcos e contadores numéricos.