Animação programática de imagens de plano de fundo
Há duas maneiras principais de animar imagens de plano de fundo:
- Use CSS Sprites para atualizar um
background-positionem JS . - Hacks com
.toDataURL().
A primeira opção é ótima se você tiver a imagem com antecedência, mas e se a fonte precisar ser gerada de maneira programática, por exemplo, por um <canvas>? A solução para o problema nº 1 é usar .toDataURL() na tela e definir o plano de fundo como o URL gerado:
while(1) {
var url = canvas.toDataURL('image/jpeg');
el.style.background = 'url(' + url + ')';
}
Isso tem dois problemas:
- Os URLs
data:adicionam uma sobrecarga de tamanho de aproximadamente 33% à imagem resultante. - Muitos toques no DOM (
el.style).
Ambos os métodos são ineficientes e inaceitáveis para um web app de 60 fps sempre fluido.
Usar o canvas 2D como plano de fundo
Acontece que há uma API não padrão que o WebKit tem há anos e que pode usar o canvas como origem de um plano de fundo. Infelizmente, não há uma especificação publicada para esse recurso.
Primeiro, em vez de especificar um URL para o retorno:
.bg {
background: url(bg.png) no-repeat 50% 50%;
}
use -webkit-canvas(), referenciando um identificador de string a um contexto de tela:
.canvas-bg {
background: -webkit-canvas(animation) no-repeat 50% 50%;
}
Em seguida, precisamos criar o contexto 2D com uma versão especial de .getContext():
var ctx = document.getCSSCanvasContext('2d', 'animation', 300, 300);
Mais informações de Dave Hyatt:
Animações
Como visto na demonstração, podemos reutilizar requestAnimationFrame() para acionar uma animação. Isso é ótimo porque, depois que as coisas são conectadas, a associação entre CSS e o elemento canvas é preservada. Não é necessário mexer no DOM.
A demonstração não está animada no Chrome?
O canal estável atual do Chrome (versão 23) tem crbug.com/161699, que impede que uma animação requestAnimationFrame() atualize o plano de fundo corretamente. Isso foi corrigido no Chrome 25 (atualmente Canary). A demonstração também deve funcionar bem no Safari atual.
Benefícios de performance
Estamos falando de tela. As animações aceleradas por hardware agora estão totalmente em funcionamento (pelo menos para os navegadores em que esse recurso funciona). E, só para reiterar, não é necessário manipular o DOM do JS.
Usar WebGL como plano de fundo
Espere um pouco. Isso significa que podemos usar o WebGL para alimentar um plano de fundo CSS? Claro que sim! O WebGL é apenas um contexto 3D para o canvas. Basta trocar "2d" por "experimental-webgl" e pronto.
var gl = document.getCSSCanvasContext('experimental-webgl', 'animation', 300, 150);
Confira uma prova de conceito que contém uma div com o plano de fundo desenhado usando sombreadores de vértice e fragmento: DEMONSTRAÇÃO
Outras abordagens
Vale lembrar que a Mozilla tem -moz-element() (MDN) há algum tempo. Isso faz parte da especificação CSS Image Values and Replaced Content Module Level 4 e permite criar uma imagem gerada de HTML arbitrário: vídeos, canvas, conteúdo DOM...o que você quiser. No entanto, há problemas de segurança ao ter acesso total às imagens de snapshot do DOM. É por isso que outros navegadores não adotaram esse recurso.