GSAP como director temporal: tweens, timelines, easing y stagger en 3D

Aprende a usar `gsap.to()`, `gsap.from()`, `gsap.set()` y `timeline()` para animar objetos 3D con intención. La meta no es mover por mover, sino secuenciar entradas, énfasis y respiración visual en una escena R3F.

Una escena 3D empieza a parecer profesional cuando el tiempo deja de estar improvisado. GSAP no solo anima propiedades: organiza intención. Decide qué entra primero, qué se enfatiza, cuánto tarda cada gesto y cómo se relacionan unas capas con otras.

En 3D eso importa el doble. Si mueves cámara, objeto, luces y materiales sin una gramática temporal clara, la escena se siente caótica aunque el modelado sea bueno. El `timeline` convierte esa suma de impulsos en una secuencia dirigida.

En esta lección verás la función real de `gsap.to()`, `gsap.from()` y `gsap.set()`, y por qué `ease` y `stagger` no son maquillaje, sino parte de la percepción física y del ritmo visual.

La meta práctica es componer una microcoreografía clara para un objeto 3D: entrada, énfasis, asentamiento y repetición controlada.

  • No todos los movimientos se describen igual. El método cambia la intención.
  • `gsap.to()` mueve un valor desde su estado actual hasta el destino indicado. Es la opción más natural cuando el objeto ya existe en escena y quieres dirigirlo a un nuevo estado visible.
  • `gsap.from()` es muy útil para entradas y revelados: defines el punto de partida y dejas que el objeto vuelva a su estado base. `gsap.set()` no anima: prepara el escenario. Por eso suele usarse para colocar la pieza en su pose de salida antes de empezar un timeline.
  • Un timeline no es comodidad sintáctica; es estructura narrativa.
  • Cuando cada propiedad vive en una llamada separada, el conjunto es difícil de leer, sincronizar o ajustar. Un `timeline` te permite encadenar movimientos, superponer acciones con etiquetas de tiempo y revisar la escena como una partitura.

Qué hace cada tween y cuándo usarlo

No todos los movimientos se describen igual. El método cambia la intención.

`gsap.to()` mueve un valor desde su estado actual hasta el destino indicado. Es la opción más natural cuando el objeto ya existe en escena y quieres dirigirlo a un nuevo estado visible.

`gsap.from()` es muy útil para entradas y revelados: defines el punto de partida y dejas que el objeto vuelva a su estado base. `gsap.set()` no anima: prepara el escenario. Por eso suele usarse para colocar la pieza en su pose de salida antes de empezar un timeline.

El timeline como director de escena

Un timeline no es comodidad sintáctica; es estructura narrativa.

Cuando cada propiedad vive en una llamada separada, el conjunto es difícil de leer, sincronizar o ajustar. Un `timeline` te permite encadenar movimientos, superponer acciones con etiquetas de tiempo y revisar la escena como una partitura.

Esto es especialmente importante en 3D porque muchas transformaciones deben convivir: posición, rotación, escala, intensidad de una luz o entrada de textos DOM superpuestos.

  • Usa `defaults` para mantener consistencia de duración y easing.
  • Usa `"<"` para empezar una animación junto a la anterior.
  • Usa `">"` o desplazamientos relativos cuando quieras respiración entre beats.
  • Piensa el timeline en términos de capítulos: entrada, foco, salida, loop.

Easing: la física percibida de tu escena

Un mal easing puede arruinar una buena composición.

El `ease` controla cómo cambia la velocidad. En una demo de producto, `power2.out` o `power3.out` suelen dar entradas limpias; `expo.out` aporta sensación premium; `none` tiene sentido cuando el movimiento debe seguir una velocidad constante, por ejemplo en trayectorias ligadas al scroll.

Usar un easing equivocado produce sensación de juguete barato o animación artificial. El easing no es decorativo: transmite peso, intención y materialidad.

Stagger: repartir el tiempo para que la escena respire

El stagger convierte un bloque repetido en una secuencia legible.

Cuando varios objetos comparten función visual, el `stagger` evita que todos reaccionen a la vez. En una fila de partículas, esferas o tarjetas 3D, esa diferencia temporal crea lectura, ritmo y profundidad percibida.

En 3D conviene usarlo con sutileza. Un stagger excesivo puede romper cohesión. El objetivo no es hacer ruido: es escalonar atención.

Cómo integrar GSAP en R3F sin pelearte con React

La clave está en animar refs, no estado React.

Las transformaciones que ocurren muchas veces por segundo no deben vivir en `useState`. En R3F lo habitual es apuntar a objetos Three.js con `useRef` y dejar que GSAP anime sus propiedades imperativas. Si ese patrón aún no lo tienes sólido, repasa <a href="/curso/react/leccion/react-useref-y-dom-medio/">useRef en React</a> antes de complicar la escena.

React organiza la escena; GSAP dirige su evolución temporal. Cuando mezclas ambos roles correctamente, el código sigue siendo mantenible. Cuando no, aparecen re-renders innecesarios, dependencias raras y bugs de sincronización. Esa frontera encaja muy bien con la mentalidad de <a href="/curso/react/leccion/react-useeffect-ciclo-vida-medio/">useEffect y sincronización externa</a>.

  • Usa `useRef` para mallas, grupos y luces que deban animarse.
  • Inicializa `gsap.timeline()` dentro de `useEffect` o `useGSAP`.
  • Limpia timelines si el componente puede desmontarse.
  • No conviertas cada frame en una actualización de estado React.
Animaciones 3D en la Web
02

GSAP como director temporal: tweens, timelines, easing y stagger en 3D

Aprende a usar `gsap.to()`, `gsap.from()`, `gsap.set()` y `timeline()` para animar objetos 3D con intención. La meta no es mover por mover, sino secuenciar entradas, énfasis y respiración visual en una escena R3F.

Código del tema: gsap.to() · timeline() · stagger

📘 Teoría

Qué hace cada tween y cuándo usarlo

No todos los movimientos se describen igual. El método cambia la intención.

`gsap.to()` mueve un valor desde su estado actual hasta el destino indicado. Es la opción más natural cuando el objeto ya existe en escena y quieres dirigirlo a un nuevo estado visible.

`gsap.from()` es muy útil para entradas y revelados: defines el punto de partida y dejas que el objeto vuelva a su estado base. `gsap.set()` no anima: prepara el escenario. Por eso suele usarse para colocar la pieza en su pose de salida antes de empezar un timeline.

1

`gsap.to()`

Sirve para llevar el objeto al estado final que quieres contar.

2

`gsap.from()`

Ideal para entradas donde la pose actual ya es tu composición final.

3

`gsap.set()`

Prepara sin transición: coloca, oculta o inicializa antes de la secuencia.

4

Error típico

Encadenar muchos `to()` sueltos sin relación temporal clara.

Patrón base: preparar y luego animar
gsap.set(mesh.position, { y: -1.2, x: -0.6 });

gsap.to(mesh.position, {
  y: 0,
  x: 0,
  duration: 1.1,
  ease: "power3.out"
});

El timeline como director de escena

Un timeline no es comodidad sintáctica; es estructura narrativa.

Cuando cada propiedad vive en una llamada separada, el conjunto es difícil de leer, sincronizar o ajustar. Un `timeline` te permite encadenar movimientos, superponer acciones con etiquetas de tiempo y revisar la escena como una partitura.

Esto es especialmente importante en 3D porque muchas transformaciones deben convivir: posición, rotación, escala, intensidad de una luz o entrada de textos DOM superpuestos.

  • Usa `defaults` para mantener consistencia de duración y easing.
  • Usa `""` para empezar una animación junto a la anterior.
  • Usa `">"` o desplazamientos relativos cuando quieras respiración entre beats.
  • Piensa el timeline en términos de capítulos: entrada, foco, salida, loop.

Easing: la física percibida de tu escena

Un mal easing puede arruinar una buena composición.

El `ease` controla cómo cambia la velocidad. En una demo de producto, `power2.out` o `power3.out` suelen dar entradas limpias; `expo.out` aporta sensación premium; `none` tiene sentido cuando el movimiento debe seguir una velocidad constante, por ejemplo en trayectorias ligadas al scroll.

Usar un easing equivocado produce sensación de juguete barato o animación artificial. El easing no es decorativo: transmite peso, intención y materialidad.

1

`power3.out`

Entrada elegante y controlada para objetos hero.

2

`expo.out`

Sensación premium y rápida al inicio con desaceleración marcada.

3

`back.out()`

Útil para enfatizar un detalle, pero conviene usarlo con moderación.

4

`none`

Velocidad constante; muy útil en trayectorias o sincronización exacta.

Stagger: repartir el tiempo para que la escena respire

El stagger convierte un bloque repetido en una secuencia legible.

1

Cuando varios objetos comparten función visual, el `stagger` evita que todos reaccionen a la vez. En una fila de partículas, esferas o tarjetas 3D, esa diferencia temporal crea lectura, ritmo y profundidad percibida.

2

En 3D conviene usarlo con sutileza. Un stagger excesivo puede romper cohesión. El objetivo no es hacer ruido: es escalonar atención.

Idea base con varias referencias
gsap.to(items.map((item) => item.scale), {
  x: 1.2,
  y: 1.2,
  z: 1.2,
  duration: 0.45,
  stagger: 0.12,
  yoyo: true,
  repeat: 1,
  ease: "back.out(1.8)"
});

Cómo integrar GSAP en R3F sin pelearte con React

La clave está en animar refs, no estado React.

Las transformaciones que ocurren muchas veces por segundo no deben vivir en `useState`. En R3F lo habitual es apuntar a objetos Three.js con `useRef` y dejar que GSAP anime sus propiedades imperativas. Si ese patrón aún no lo tienes sólido, repasa useRef en React antes de complicar la escena.

React organiza la escena; GSAP dirige su evolución temporal. Cuando mezclas ambos roles correctamente, el código sigue siendo mantenible. Cuando no, aparecen re-renders innecesarios, dependencias raras y bugs de sincronización. Esa frontera encaja muy bien con la mentalidad de useEffect y sincronización externa.

  • Usa `useRef` para mallas, grupos y luces que deban animarse.
  • Inicializa `gsap.timeline()` dentro de `useEffect` o `useGSAP`.
  • Limpia timelines si el componente puede desmontarse.
  • No conviertas cada frame en una actualización de estado React.

🧭 Visuales clave

Timeline de una microcoreografía 3D

Ayuda a leer un timeline como estructura de dirección visual y no como una colección de tweens inconexos.

Diagrama temporal de una animación 3D con GSAP mostrando preparación, entrada, giro, énfasis y reposo

🧪 Aprende probando

Ejemplo Demo guiada: coreografía de entrada con GSAP en JavaScript Este preview usa GSAP sobre un panel con perspectiva CSS para que puedas ver el timeline funcionando en el playground. La lógica temporal es la misma que luego aplicarás a objetos 3D reales.
Ejemplo Ejemplo resuelto: stagger sutil para crear ritmo visual Aunque aquí se aplica sobre elementos DOM, la lógica es idéntica a animar varias mallas o luces en 3D: repartir el tiempo para escalonar atención.
Ejemplo Demo interactiva: botones magnéticos con GSAP Explora una microinteracción donde el botón persigue el cursor con inercia suave y refuerza la sensación de objeto reactivo sin romper la legibilidad del CTA.
Ejemplo Demo interactiva: morph de texto con TextPlugin Observa cómo una pieza tipográfica puede cambiar mensaje, ritmo y tono visual usando GSAP como director temporal y no como simple efecto decorativo.
Ejemplo Demo interactiva: colección de demos GSAP + Three.js Explora varios ejemplos prácticos de integración entre GSAP y Three.js, incluyendo animaciones de texto, partículas, scroll y más.

🏁 Retos

Reto Reto 1: construye una microsecuencia con entrada, foco y reposo Secuencia tres fases claras: entrada, giro y asentamiento. Aquí el foco está en la estructura temporal, no en la tecnología concreta del render.

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros 😉.

Esta la hice en febrero de 2026 para facilitar el aprendizaje de mis alumnxs. Aprender desarrollo web practicando. La idea es que crezca semanalmente con nuevos temas, tests y retos.

Inspirado en MDN, en W3Schools, en Codepen, en el crack de Manz y en mil sitios de documentación sobre desarrollo web. Quería aportar además de bloques teóricos con ejemplos, la gamificación de los retos y el sistema de test que ya tenía en culTest .

Si te gustó, si no te gustó, si quieres saludarme, o invitarme a 🍻 no dudes en escribirme en cristianeslava@gmail.com .