Como animar imagens de plano de fundo de forma programática
Há duas maneiras principais de animar imagens de plano de fundo:
- Use sprites CSS para atualizar um
background-position
em JS . - Hacks com
.toDataURL()
.
A primeira funciona muito bem se você tiver a imagem com antecedência, mas e se a origem precisar ser gerada programaticamente, por exemplo, por um <canvas>
? A solução para o item 1 é usar .toDataURL()
na tela e definir o plano de fundo para o URL gerado:
while(1) {
var url = canvas.toDataURL('image/jpeg');
el.style.background = 'url(' + url + ')';
}
Há dois problemas com isso:
- Os URLs
data:
adicionam um overhead de tamanho de aproximadamente 33% à imagem resultante. - Uma tonelada de contato com o DOM (
el.style
).
Esses dois métodos são ineficientes: inaceitáveis para um app da Web sempre suave e com 60 fps.
Usar uma tela 2D como plano de fundo
Há uma API não padrão que o WebKit tem há anos e que pode usar a tela como a origem de um plano de fundo. Infelizmente, não há especificações publicadas para esse recurso.
Em vez de especificar um URL para a página anterior, faça o seguinte:
.bg {
background: url(bg.png) no-repeat 50% 50%;
}
Use -webkit-canvas()
, referenciando um identificador de string para 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 mostrado na demonstração, podemos reutilizar requestAnimationFrame()
para gerar uma animação. Isso é ótimo, porque, depois que as coisas são conectadas, a associação entre o CSS e o elemento de tela é 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 desempenho
Estamos falando de tela. As animações aceleradas por hardware agora estão totalmente em uso (pelo menos nos navegadores em que esse recurso funciona). E, apenas para reiterar, não é necessário molestar o DOM do JS.
Usar o WebGL como plano de fundo
Espera aí. Isso significa que podemos usar um plano de fundo CSS com o WebGL? Claro que sim. O WebGL é apenas um contexto 3D para a tela. Basta trocar "experimental-webgl" por "2d".
var gl = document.getCSSCanvasContext('experimental-webgl', 'animation', 300, 150);
Confira uma prova de conceito que contém um div com o plano de fundo desenhado usando shaders de vértice e fragmento: DEMONSTRAÇÃO
Outras abordagens
Vale ressaltar 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 a partir de HTML arbitrário: vídeos, tela, conteúdo DOM etc. No entanto, há questões de segurança relacionadas ao acesso total a imagens de snapshot do DOM. Esse é o principal motivo pelo qual outros navegadores não adotaram esse recurso.