Images de fond basées sur un canevas

Eric Bidelman

Animer des images de fond de façon programmatique

Il existe deux principales méthodes pour animer les images de fond:

  1. Utilisez des sprites CSS pour mettre à jour un élément background-position en JavaScript .
  2. Hacks avec .toDataURL() .

La première fonctionne très bien si vous disposez de l'image à l'avance, mais que se passe-t-il si votre source doit être générée de façon programmatique, par exemple par un élément <canvas> ? La solution numéro 1 consiste à utiliser .toDataURL() sur le canevas et à définir l'arrière-plan sur l'URL générée:

while(1) {
    var url = canvas.toDataURL('image/jpeg');
    el.style.background = 'url(' + url + ')';
}

Cela présente deux problèmes:

  1. Les URL data: ajoutent une surcharge de taille d'environ 33% à l'image obtenue.
  2. Beaucoup d'interactions DOM (el.style).

Ces deux méthodes sont inefficaces: elles ne sont pas acceptables pour une application Web toujours fluide à 60 FPS.

Utilisation d'un canevas 2D en arrière-plan

Canvas en arrière-plan de démonstration
DÉMO

Il s'avère que WebKit possède une API non standard depuis des années qui peut utiliser une toile comme source d'arrière-plan. Malheureusement, il n'existe aucune spécification publiée pour cette fonctionnalité.

Premièrement, au lieu de spécifier une URL pour l'arrière-plan:

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

Utilisez -webkit-canvas(), en référençant un identifiant de chaîne à un contexte de canevas:

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

Nous devons ensuite créer le contexte 2D avec une version spéciale de .getContext():

var ctx = document.getCSSCanvasContext('2d', 'animation', 300, 300);

Informations supplémentaires de Dave Hyatt:

Animations

Comme illustré dans la démonstration, nous pouvons réutiliser requestAnimationFrame() pour générer une animation. C'est une très bonne idée, car une fois les éléments connectés, l'association entre le CSS et l'élément de canevas est préservée. Il n'est pas nécessaire de manipuler le DOM.

La démo n'est pas animée dans Chrome ?

La version stable actuelle de Chrome (version 23) est crbug.com/161699, ce qui empêche une animation requestAnimationFrame() de mettre à jour correctement l'arrière-plan. Ce problème a été résolu dans Chrome 25 (actuellement Canary). La démonstration devrait également fonctionner correctement dans la version actuelle de Safari.

Avantages en termes de performances

Il s'agit ici de toile. Les animations accélérées par le matériel sont désormais entièrement actives (du moins pour les navigateurs dans lesquels cette fonctionnalité est disponible). Pour rappel, il n'est pas nécessaire d'agresser le DOM à partir de JavaScript.

Utiliser WebGL en arrière-plan

Veuillez patienter. Cela signifie-t-il que nous pouvons alimenter un arrière-plan CSS à l'aide de WebGL ? C'est bien le cas ! WebGL est simplement un contexte 3D pour les canevas. Il vous suffit de remplacer "experimental-webgl" par "2d", et le tour est joué.

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

Voici une démonstration de faisabilité qui contient un élément div dont l'arrière-plan est dessiné à l'aide de nuanceurs de sommet et de fragment: DEMO.

Autres approches

Il convient de noter que Mozilla utilise -moz-element() (MDN) depuis un certain temps. Cela fait partie de la spécification Valeurs d'image CSS et contenu remplacé de niveau 4 et vous permet de créer une image générée à partir d'un code HTML arbitraire: vidéos, canevas, contenu DOM, etc. Toutefois, l'accès complet aux instantanés du DOM pose des problèmes de sécurité. C'est principalement pour cette raison que les autres navigateurs n'ont pas adopté cette fonctionnalité.