Cómo animar imágenes de fondo de forma programática
Existen dos formas principales de animar imágenes de fondo:
- Usar sprites de CSS para actualizar un
background-positionen JS . - Hacks con
.toDataURL().
La primera opción funciona muy bien si tienes la imagen con anticipación, pero ¿qué sucede si tu fuente debe generarse de forma programática, por ejemplo, con un <canvas>? La solución para el punto 1 es usar .toDataURL() en el lienzo y establecer el fondo en la URL generada:
while(1) {
var url = canvas.toDataURL('image/jpeg');
el.style.background = 'url(' + url + ')';
}
Esto tiene dos problemas:
- Las URLs
data:agregan una sobrecarga de tamaño de aproximadamente el 33% a la imagen resultante. - Una gran cantidad de toques de DOM (
el.style).
Ambos métodos son ineficientes: inaceptables para una app web de 60 fps siempre fluida.
Cómo usar el lienzo 2D como fondo
Resulta que existe una API no estándar que WebKit tiene desde hace años y que puede tomar el lienzo como fuente para un fondo. Sin embargo, lamentablemente, no hay una especificación publicada para esta función.
Primero, en lugar de especificar una URL para la parte posterior:
.bg {
background: url(bg.png) no-repeat 50% 50%;
}
usa -webkit-canvas(), que hace referencia a un identificador de cadena a un contexto de lienzo:
.canvas-bg {
background: -webkit-canvas(animation) no-repeat 50% 50%;
}
A continuación, debemos crear el contexto 2D con una versión especial de .getContext():
var ctx = document.getCSSCanvasContext('2d', 'animation', 300, 300);
Más información de Dave Hyatt:
Animaciones
Como se ve en la demostración, podemos reutilizar requestAnimationFrame() para controlar una animación. Esto es genial porque, una vez que las cosas están conectadas, se conserva la asociación entre CSS y el elemento de lienzo. No es necesario manipular el DOM.
¿La demostración no está animada en Chrome?
El canal estable actual de Chrome (versión 23) tiene crbug.com/161699, que impide que una animación requestAnimationFrame() actualice el fondo correctamente. Esto se corrigió en Chrome 25 (actualmente Canary). La demostración también debería funcionar bien en el Safari actual.
Beneficios de rendimiento
Estamos hablando de lienzo aquí. Las animaciones aceleradas por hardware ahora están completamente en juego (al menos para los navegadores en los que funciona esta función). Y, para reiterar, no es necesario manipular el DOM desde JS.
Cómo usar WebGL como fondo
Espera un segundo. ¿Esto significa que podemos potenciar un fondo de CSS con WebGL? ¡Por supuesto que sí! WebGL es simplemente un contexto 3D para el lienzo. Solo cambia "experimental-webgl" en lugar de "2d" y listo.
var gl = document.getCSSCanvasContext('experimental-webgl', 'animation', 300, 150);
Aquí tienes una prueba de concepto que contiene un div con su fondo dibujado con sombreadores de vértices y fragmentos: DEMO
Otros enfoques
Cabe destacar que Mozilla tiene -moz-element() (MDN) desde hace bastante tiempo. Esto forma parte de la especificación CSS Image Values and Replaced Content Module Level 4 y te permite crear una imagen generada a partir de HTML arbitrario: videos, lienzos, contenido DOM, lo que quieras. Sin embargo, existen problemas de seguridad relacionados con tener acceso completo a las imágenes de instantáneas del DOM. Este es el motivo principal por el que otros navegadores no adoptaron dicha función.