OffscreenCanvas : accélérez les opérations de canevas avec un nœud de calcul Web

Tim Dresser

Canvas est une méthode couramment utilisée de dessiner toutes sortes de graphismes à l'écran et d'entrer dans l'univers de WebGL. Il permet de dessiner des formes, des images, d'exécuter des animations, ou même d'afficher et de traiter du contenu vidéo. Il est souvent utilisé pour créer des expériences utilisateur attrayantes dans les applications Web multimédias et des jeux en ligne.

Il est compatible avec des scripts, ce qui signifie que le contenu dessiné sur le canevas peut être créé par programmation, par exemple, en JavaScript. Cela donne au canevas une grande flexibilité.

Parallèlement, sur les sites Web modernes, l'exécution de scripts est l'une des principales sources des problèmes de réactivité des utilisateurs. Comme la logique du canevas et le rendu s'effectuent sur le même thread que l'interaction utilisateur, les calculs (parfois lourds) impliqués dans les animations peuvent nuire au véritable et les performances perçues.

Heureusement, OffscreenCanvas est une réponse à cette menace.

Navigateurs pris en charge

  • 69
  • 79
  • 105
  • 16.4

Source

Auparavant, les fonctionnalités de dessin sur canevas étaient liées à l'élément <canvas>, ce qui signifie qu'il dépendait directement du DOM. Comme son nom l'indique, dissocie le DOM de l'API Canvas en le déplaçant hors de l'écran.

Grâce à ce découplage, le rendu d'OffscreenCanvas est entièrement dissocié du DOM offre donc des améliorations de vitesse par rapport au canevas standard, car il n'y a pas de synchronisation entre les deux.

En outre, il peut être utilisé dans un Web Worker, DOM disponible. Cela permet toutes sortes de cas d'utilisation intéressants.

Utiliser OffscreenCanvas dans un nœud de calcul

Nœuds de calcul sont la version Web des threads : ils vous permettent d'exécuter des tâches en arrière-plan.

En déplaçant une partie de vos scripts vers un nœud de calcul, vous donnez à votre application plus de marge de manœuvre pour effectuer les tâches essentielles sur le thread principal. Sans OffscreenCanvas, il n'existait aucun moyen d'utiliser l'API Canvas dans un nœud de calcul, car qu'aucun DOM n'était disponible.

OffscreenCanvas ne dépend pas du DOM. Il peut donc être utilisé. L'exemple suivant utilise OffscreenCanvas pour calculer une couleur de dégradé dans un nœud de calcul:

// file: worker.js
function getGradientColor(percent) {
  const canvas = new OffscreenCanvas(100, 1);
  const ctx = canvas.getContext('2d');
  const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  gradient.addColorStop(0, 'red');
  gradient.addColorStop(1, 'blue');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, ctx.canvas.width, 1);
  const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
  const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
  return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}

getGradientColor(40);  // rgba(152, 0, 104, 255 )

Débloquer le thread principal

Déplacer les calculs lourds vers un nœud de calcul vous permet de libérer de l'espace des ressources importantes sur le thread principal. Utiliser la commande transferControlToOffscreen pour dupliquer le canevas normal sur une instance OffscreenCanvas. Opérations appliquées à L'application OffscreenCanvas s'affiche automatiquement sur le canevas source.

const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);

Dans l'exemple suivant, le calcul lourd se produit lorsque le thème de couleurs change : il doit prendre quelques millisecondes, même sur un bureau rapide. Vous pouvez choisir d'exécuter des animations sur le thread principal ou dans le nœud de calcul. Dans le cas du thread principal, vous ne pouvez pas interagir avec le bouton est en cours d'exécution, le thread est bloqué. Pour le travailleur, il n'y a aucun impact sur réactivité de l'interface utilisateur.

Démonstration

Cela fonctionne également dans l'autre sens: le thread principal occupé n'a aucune incidence sur l'animation en cours d'exécution. un nœud de calcul. Vous pouvez utiliser cette fonctionnalité pour éviter les à-coups visuels et garantir une animation fluide. malgré le trafic du thread principal, comme illustré dans la démonstration suivante.

Démonstration

Dans le cas d'un canevas standard, l'animation s'arrête lorsque le thread principal est artificiellement surchargé. tandis que l'animation hors écran basée sur les nœuds de calcul est fluide.

Étant donné que l'API OffscreenCanvas est généralement compatible avec l'élément Canvas standard, vous pouvez l'utiliser comme une amélioration progressive, également avec certaines des principales bibliothèques graphiques du marché.

Par exemple, vous pouvez la détecter et, le cas échéant, l'utiliser avec Three.js en spécifiant l'option canevas dans le constructeur du moteur de rendu:

const canvasEl = document.querySelector('canvas');
const canvas =
  'OffscreenCanvas' in window
    ? canvasEl.transferControlToOffscreen()
    : canvasEl;
canvas.style = {width: 0, height: 0};
const renderer = new THREE.WebGLRenderer({canvas: canvas});

Le seul problème ici est que Three.js s'attend à ce que le canevas possède les propriétés style.width et style.height. Comme OffscreenCanvas, qui est totalement dissocié du DOM, vous devez le fournir vous-même. soit en les bouchonnant, soit en fournissant une logique qui lie ces valeurs à l'original les dimensions de la toile.

L'exemple suivant montre comment exécuter une animation Three.js de base dans un nœud de calcul:

Démonstration

Gardez à l'esprit que certaines API liées au DOM ne sont pas facilement disponibles dans un nœud de calcul. Par conséquent, si vous si vous souhaitez utiliser des fonctionnalités Three.js plus avancées telles que les textures, vous aurez peut-être besoin d'autres solutions de contournement. Pour savoir comment vous lancer dans ces tests, consultez la vidéo de la conférence Google I/O 2017.

Si vous utilisez de façon intensive les fonctionnalités graphiques des canevas, OffscreenCanvas peut vous aider influencer les performances de votre application. Mettre les contextes de rendu de canevas à la disposition des nœuds de calcul augmente le parallélisme dans les applications web et utilise une meilleure utilisation des systèmes multicœurs.

Ressources supplémentaires