Imágenes de fondo basadas en lienzos

Cómo animar imágenes de fondo de manera programática

Existen dos formas principales en que las personas animan las imágenes de fondo:

  1. Usa objetos CSS para actualizar un background-position en JS .
  2. Trucos con .toDataURL() .

La primera funciona muy bien si tienes la imagen con anticipación, pero ¿qué sucede si tu fuente debe generarse de manera programática, por ejemplo, mediante un <canvas>? La solución para #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:

  1. Las URLs data: agregan una sobrecarga de tamaño de aproximadamente el 33% a la imagen resultante.
  2. Muchos DOM tocan (el.style).

Estos métodos son ineficientes: es inaceptable para una app web de 60 fps que es fluida y siempre fluida.

Usar el lienzo 2D como fondo

Demostración del lienzo como una función en segundo plano
DEMOSTRACIÓN

Resulta que existe una API no estándar que WebKit tuvo durante años y que puede tomar el lienzo como la fuente de un fondo. Lamentablemente, no hay ninguna especificación publicada para este elemento.

Primero, en lugar de especificar una URL para el retroceso:

.bg {
    background: url(bg.png) no-repeat 50% 50%;
}

Usa -webkit-canvas() y haz referencia a un identificador de cadenas para un contexto de lienzo:

.canvas-bg {
    background: -webkit-canvas(animation) no-repeat 50% 50%;
}

A continuación, debemos crear el contexto en 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 volver a usar requestAnimationFrame() para controlar una animación. Esto es genial porque, una vez que todo está conectado, se conserva la asociación entre CSS y el elemento lienzo. No es necesario manipular el DOM.

¿La demostración no es animada en Chrome?

El canal estable actual de Chrome (versión 23) tiene crbug.com/161699, que evita que una animación requestAnimationFrame() actualice el fondo correctamente. Este problema se solucionó en Chrome 25 (actualmente Canary). La demostración también debería funcionar bien en Safari actual.

Beneficios de rendimiento

Aquí hablamos de lienzo. Las animaciones aceleradas por hardware ya están completamente en juego (al menos para los navegadores en los que funciona esta función). Solo para reiterar, no es necesario modelar el DOM desde JS.

Cómo usar WebGL como fondo

Espera un momento. ¿Esto significa que podemos potenciar un fondo CSS con webgl? Por supuesto que sí. WebGL es solo un contexto 3D para el lienzo. Solo cambia a "experimental-webgl" en lugar de "2d" y listo.

var gl = document.getCSSCanvasContext('experimental-webgl', 'animation', 300, 150);

Esta es una prueba de concepto que contiene un elemento div cuyo fondo se dibujó con sombreadores de vértices y fragmentos: DEMO

Otros enfoques

Vale la pena señalar que Mozilla tiene -moz-element() (MDN) desde hace bastante tiempo. Esto forma parte de la especificación de Valores de imagen de CSS y módulo de contenido reemplazado de nivel 4, y te permite crear una imagen generada a partir de HTML arbitrario: videos, lienzos, contenido DOM, etc. Sin embargo, existen problemas de seguridad con respecto a tener acceso completo a instantáneas de imágenes del DOM. Esta es principalmente la razón por la que otros navegadores no han adoptado esa función.