PTENES
MÓDULO 2.1

✍️ Animaciones de texto

9 plantillas, 9 maneras diferentes de mover el texto. Desde revelar letra por letra con stagger hasta una onda senoidal y glitch RGB: cada plantilla enseña un patrón que se repite en decenas de situaciones reales.

9
Plantillas
40
Minutos
Inter
Nivel
Práctico
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 video animado
1

✍️ Visión general — La categoría Texto

El texto animado no es opcional en un video: es el principal vehículo de información. La categoría Texto de la biblioteca cubre 9 patrones distintos, desde revelar letra por letra hasta una onda senoidal y un glitch RGB. Entender cuál usar en cada contexto es lo que separa un video superficial de uno con identidad visual.

🎯 Cuándo usar animación de texto

Revelar información progresivamente:

  • →animated-text o typewriter para datos que «llegan»
  • →slide-text para entradas direccionales (slide-in)

Llamar la atención sobre el texto existente:

  • →pulsing-text para una respiración suave y continua
  • →glitch-text para estilo retro/hacker

✓ Cuándo el texto se anima bien

  • ✓Ritmo alineado con la narración o la música de fondo.
  • ✓Duración proporcional a la longitud del texto.
  • ✓Estilo de animación coherente con el tono del video.

✗ Cuándo perjudica

  • ✗Animación más rápida que la lectura: el texto desaparece antes de que puedas leerlo.
  • ✗Glitch o bounce en un contexto corporativo serio.
  • ✗Varias animaciones diferentes en la misma escena.
9 plantillas
Categoría de texto
3 familias
Stagger / Física / Efecto
Hook base
interpolate + spring
Patrón
Dividir → stagger → animar
2

🔤 animated-text — stagger letra por letra

La plantilla animated-text.tsx divide el texto en un array de caracteres y aplica una Sequence con from escalado por índice. Cada letra aparece con un pequeño retraso respecto de la anterior, creando el efecto de "escritura veloz" sin usar setTimeout ni estado.

animated-text.tsx — núcleo del 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 qué i * 2 y no un valor fijo?

O i * 2 es el delay: cada letra empieza 2 frames después de la anterior. Cámbialo a i * 4 y la revelación es más lenta; i * 1 deja casi todo simultáneo. El + 8 define la duración del fade individual: el tiempo que tarda la opacidad en pasar de 0 a 1.

Línea de tiempo de ejecución (texto "OLÁ"):

F0

Frame 0 — «O» empieza a aparecer

opacity de la «O» va de 0→1 en los frames 0-8. «L» y «Á» aún invisibles (opacity=0).

F2

Frame 2 — «L» empieza a aparecer con fade

"O" todavía se está animando; "L" inicia la interpolación 0→1 en los frames 2-10.

F8

Frame 8 — texto completo visible

Todos los caracteres en opacity=1. Animación completada.

Patrón
split + map + interpolate
Stagger
i × delay
Extrapolate
clamp (obligatorio)
Reutiliza en
Palabras, líneas, listas
3

🏀 bounce-text — spring con overshoot

O bounce-text.tsx usa spring() en vez de interpolate(). La diferencia visual es enorme: en lugar de subir de forma lineal, el texto "rebota": sobrepasa el destino y vuelve, como un objeto con masa y amortiguación.

bounce-text — spring con 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: cuándo usarlo

  • ✓Títulos hero que necesitan impacto visual.
  • ✓CTAs y botones que «llaman» al espectador.
  • ✓Emojis e íconos expresivos.

✗ Interpolate: cuándo usarlo

  • →Fades — spring no controla la opacidad con precisión.
  • →Movimiento horizontal exacto (deslizamiento preciso).
  • →Cualquier timing que no puede tener overshoot.

📊 Tabla de parámetros spring

ParámetroValor bajoValor alto
dampingelástico, oscila demasiadofirma rápido, sin bounce
stiffnesslento, perezosorápido, agresivo
massligero, rápidopesado, con mucha inercia
Devuelve
0 → ~1 (con overshoot)
Usa fps
siempre pasar fps
Combinar
× scale o translateY
Stagger
frame - i * delay
4

💻 glitch-text — RGB split sin biblioteca

El efecto glitch se obtiene con tres copias del mismo texto superpuestas, cada una coloreada en un canal (rojo, verde, azul) y desplazada horizontalmente de forma irregular. Todo con random() sembrado y interpolate multi-keyframe para los pulsos.

glitch-text — separación RGB 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

Con mixBlendMode: "screen", donde el rojo y el cian se superponen y producen blanco, creando el artefacto visual característico del glitch de CRT. Sin el blend mode, los colores simplemente se cubren entre sí.

⚠️ No uses Math.random() aquí

El desplazamiento del glitch debe ser determinista: usa random("glitch-r") de Remotion para las amplitudes fijas por canal. Math.random() hará que el glitch parpadee de forma diferente en cada render, lo que romperá el video en el renderizado paralelo.

Técnica
3 copias superpuestas
Blend
mixBlendMode: screen
Pulso
frame % período
Seed
random() determinístico
5

🌊 floating-bubble-text — onda senoidal

En lugar de interpolate o spring, el floating-bubble-text.tsx usa directamente Math.sin() con el frame como argumento. Cada carácter oscila con una diferencia de fase en relación con el anterior, creando una onda que recorre el texto continuamente — sin principio ni fin.

onda senoidal por carácter 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>
  );
})}

📊 Ajustar el comportamiento

frame / 12 — velocidad: un número mayor = más lento
i * 0.5 — desfase: cuanto menor, más sincrónico
* 8 — amplitud: píxeles de desplazamiento vertical
Técnica
Math.sin(frame)
Loop
Periódico automático
Fase
i × offset
Uso
Backgrounds y decoración
6

⌨️ typewriter-subtitle — cursor parpadeante

O typewriter-subtitle.tsx emula una escritura real: muestra progresivamente más caracteres del texto usando text.slice(0, visibleChars), donde visibleChars se deriva directamente del frame. El cursor parpadea con interpolate multi-keyframe.

typewriter + cursor parpadeante 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]
);

💡 Ajustar la velocidad

charsPerFrame = 0.3 escribe ~9 caracteres/seg a 30fps. Para escribir más rápido: aumenta a 0.5. Para algo lento, tipo terminal: 0.15. La fórmula Math.floor(frame * rate) es el patrón universal para «cuántos elementos mostrar hasta ahora».

Técnica
slice(0, frame×rate)
Cursor
frame % período
Velocidad
charsPerFrame
Uso
Subtítulos, código, tutoriales
7

📚 Biblioteca completa — Categoría Texto

Las 9 plantillas de la categoría, con el archivo, una descripción de una línea y el hook principal utilizado.

PlantillaDescripciónHook principal
animated-text.tsx Reveal carácter a carácter con stagger interpolate
bounce-text.tsx Entrada con overshoot elástico spring
bubble-pop-text.tsx Scale 0→1.2→1 por palabra spring
floating-bubble-text.tsx Onda sinusoidal por carácter Math.sin
glitch-text.tsx RGB split con pulso irregular interpolate + random
popping-text.tsx Scale pop independiente por palabra spring stagger
pulsing-text.tsx Respiración continua de opacidad Bucle Math.sin
slide-text.tsx Deslizamiento direccional con easing out interpolate + easing
typewriter-subtitle.tsx Escritura con cursor parpadeante slice + frame%

📌 Resumen del módulo

✓
Stagger = split + map + i × delay — el patrón universal para revelar elementos en secuencia.
✓
spring para un pop orgánico — damping bajo = rebote, damping alto = firmeza.
✓
Math.sin(frame) para loops perpetuos — onda, respiración y cualquier movimiento cíclico.
✓
Glitch = 3 copias + mixBlendMode — efecto visual complejo sin biblioteca externa.
✓
random() con semilla — aleatoriedad visual sin romper el renderizado determinista.

Próximo módulo:

2.2 — Gráficos y datos: SVG animado con interpolate, dashoffset, arcos y contadores numéricos.