Command Palette

Search for a command to run...

Animaciones en Canvas 2D: requestAnimationFrame y Técnicas de Optimización

Aprende a crear animaciones fluidas en Canvas usando requestAnimationFrame, bucles de animación, y técnicas de optimización para lograr 60 FPS.

Lectura: 16 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • requestAnimationFrame() es la API estándar para animaciones web fluidas
  • El bucle de animación limpia y redibuja cada frame
  • Usa delta time para animaciones independientes de la tasa de refresco
  • Limpia el canvas con clearRect() antes de cada frame
  • Optimiza reduciendo el número de operaciones de dibujo por frame

Introducción a las Animaciones

Las animaciones en Canvas se crean mediante un bucle que limpia y redibuja el contenido del canvas repetidamente. Este bucle debe ejecutarse a una tasa constante, idealmente 60 veces por segundo (60 FPS), para lograr una animación fluida y natural. La API requestAnimationFrame() está diseñada específicamente para este propósito.

El patrón básico de animación en Canvas es: limpiar el canvas, actualizar el estado de los objetos (posiciones, ángulos, etc.), dibujar los objetos en su nuevo estado, y repetir. Este ciclo se ejecuta indefinidamente hasta que se detenga la animación.

requestAnimationFrame vs setInterval

requestAnimationFrame() es superior a setInterval() para animaciones porque se sincroniza con el refresco del monitor, se pausa cuando la pestaña está en segundo plano (ahorrando batería), y proporciona un timestamp preciso para calcular delta time. Siempre usa requestAnimationFrame() para animaciones.

requestAnimationFrame

El método requestAnimationFrame(callback) solicita que el navegador ejecute la función callback antes del próximo repintado. El navegador optimiza esta llamada para ejecutarla a la tasa de refresco del monitor (generalmente 60 Hz), lo que resulta en animaciones fluidas y eficientes.

La función callback recibe un timestamp (en milisegundos) que indica cuándo se ejecutará el callback. Este timestamp es útil para calcular delta time, que es el tiempo transcurrido entre frames, lo que permite animaciones independientes de la tasa de refresco.

requestanimationframe.js
Loading code...

Este ejemplo muestra el patrón básico de animación usando requestAnimationFrame(). La función animar() limpia el canvas, actualiza el estado, dibuja el frame actual, y se programa a sí misma para el próximo frame usando requestAnimationFrame().

  • requestAnimationFrame() se <strong>sincroniza</strong> con el refresco del monitor
  • Se <strong>pausa</strong> cuando la pestaña está en segundo plano
  • Proporciona un <strong>timestamp</strong> para calcular delta time
  • Es más <strong>eficiente</strong> que setInterval() para animaciones
  • Permite <strong>60 FPS</strong> fluidos en la mayoría de dispositivos

Error común: Olvidar cancelar la animación

Si no cancelas la animación cuando el componente se desmonta o la página se cierra, requestAnimationFrame() continuará ejecutándose, causando memory leaks y errores. Siempre guarda el ID devuelto por requestAnimationFrame() y cancélalo con cancelAnimationFrame().

Animación Básica

Una animación básica consiste en tres pasos: limpiar el canvas, actualizar el estado de los objetos, y dibujar los objetos en su nuevo estado. El paso de limpieza es crucial porque Canvas no borra automáticamente el contenido anterior. Si no limpias, cada frame se dibujará sobre el anterior, creando un efecto de rastro.

Para crear movimiento, necesitas variables que representen el estado del objeto (posición, ángulo, escala, etc.). En cada frame, actualizas estas variables según la lógica de la animación y luego dibujas el objeto usando los valores actualizados.

animacion-basica.js
Loading code...

Este ejemplo muestra una animación básica de un círculo que se mueve. En cada frame, se limpia el canvas, se actualiza la posición del círculo, y se dibuja en la nueva posición. Cuando el círculo alcanza el borde, invierte su dirección para rebotar.

Mejor práctica para animaciones

Siempre limpia el canvas con clearRect() al inicio de cada frame. Usa delta time para que la animación sea independiente de la tasa de refresco. Separa la lógica de actualización del dibujo para un código más limpio y mantenible.

Animación de Múltiples Objetos

Para animar múltiples objetos, crea una estructura de datos (como un array) que contenga todos los objetos. En cada frame, itera sobre este array, actualiza cada objeto según su lógica específica, y luego dibuja todos los objetos. Este enfoque permite animar cientos o miles de objetos de manera eficiente.

Cada objeto puede tener sus propias propiedades de estado (posición, velocidad, color, tamaño, etc.) y su propia lógica de actualización. Esto permite crear animaciones complejas con diferentes comportamientos para cada tipo de objeto.

animacion-objetos.js
Loading code...

Este ejemplo muestra cómo animar múltiples objetos. Se crea un array de círculos, cada uno con sus propias propiedades. En cada frame, se actualiza cada círculo según su velocidad y se dibujan todos. Los círculos rebotan en los bordes del canvas.

  • Usa un <strong>array</strong> para almacenar todos los objetos animados
  • Cada objeto tiene sus propias <strong>propiedades de estado</strong>
  • Itera sobre el array para <strong>actualizar</strong> cada objeto
  • Dibuja todos los objetos después de <strong>actualizar</strong> el estado
  • Este patrón escala bien con <strong>cientos de objetos</strong>

Sistemas de partículas

El patrón de array de objetos es ideal para sistemas de partículas, donde cada partícula es un objeto independiente con su propia posición, velocidad y vida útil. Las partículas se crean, actualizan, y eliminan dinámicamente, creando efectos visuales impresionantes.

Optimización de Animaciones

Para mantener 60 FPS con animaciones complejas, necesitas optimizar el código. Las técnicas principales incluyen reducir el número de operaciones de dibujo, usar técnicas de culling (no dibujar objetos fuera de pantalla), y minimizar la creación de objetos dentro del bucle de animación.

Otras técnicas de optimización incluyen usar offscreen canvases para contenido estático, implementar dirty rectangles (solo redibujar áreas que cambiaron), y usar técnicas de pooling para reutilizar objetos en lugar de crear nuevos continuamente.

optimizacion.js
Loading code...

Este ejemplo muestra técnicas de optimización básicas. Se implementa culling para no dibujar objetos fuera de pantalla, se reutiliza el mismo array de objetos en lugar de crear nuevos, y se minimizan las operaciones de dibujo.

Mejores prácticas de optimización

Usa culling para no dibujar objetos fuera de pantalla. Implementa dirty rectangles para solo redibujar áreas que cambiaron. Usa offscreen canvases para contenido estático. Minimiza la creación de objetos en el bucle de animación usando técnicas de pooling.

Resumen: Animaciones en Canvas

Conceptos principales:

  • requestAnimationFrame() es la API estándar para animaciones web
  • El bucle de animación limpia, actualiza y dibuja cada frame
  • Delta time permite animaciones independientes de la tasa de refresco
  • Usa arrays para animar múltiples objetos eficientemente
  • La optimización es crucial para mantener 60 FPS

Mejores prácticas:

  • Siempre limpia el canvas con clearRect() al inicio de cada frame
  • Cancela la animación con cancelAnimationFrame() cuando no se necesite
  • Usa delta time para animaciones consistentes en diferentes dispositivos
  • Implementa culling para no dibujar objetos fuera de pantalla
  • Reutiliza objetos en lugar de crear nuevos en cada frame