C
Chrome for Developers
#HTML-in-Canvas#WebGPU#WebGL

Construire des UIs de Nouvelle Génération avec l'API HTML-in-Canvas

Découvrez l'API HTML-in-Canvas pour intégrer du contenu DOM interactif et accessible directement dans les textures WebGL/WebGPU, permettant des UIs web avancées et performantes.

5 min de lectureGuide IA

Introduction

Introduction
L'API HTML-in-Canvas permet d'intégrer du contenu DOM directement dans une texture Canvas, WebGL ou WebGPU, offrant la possibilité de créer des interfaces utilisateur visuellement riches et interactives tout en conservant les fonctionnalités natives du navigateur comme l'accessibilité et la traduction.

Précis de configuration

Élément Version / Lien
Langage / Runtime JavaScript
APIs requises HTML-in-Canvas API (via layoutsubtree, drawElementImage, texElementImage2D, copyElementImageToTexture, getElementTransform)
Librairies principales Three.js (support expérimental), PlayCanvas (support expérimental)
Clés / credentials nécessaires Inscription à l'Origin Trial de Chrome pour le déploiement en production (goo.gl/HIC-OT)

Guide étape par étape

Guide étape par étape

Étape 1 — Configurer le Canvas avec layoutsubtree et ajouter du contenu HTML

Pour que le navigateur reconnaisse le contenu HTML à l'intérieur du Canvas et l'expose aux fonctionnalités du navigateur (comme l'accessibilité et le test de clics), vous devez définir la propriété layoutsubtree sur la balise <canvas> et y insérer votre HTML.

<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
  <div id="form_element">
    name: <input>
  </div>
</canvas>

Étape 2 — Rendre l'élément UI dans le Canvas (Contexte 2D)

Une fois le HTML ajouté, vous devez explicitement appeler une API de rendu pour dessiner le contenu DOM dans le Canvas. Pour un contexte 2D, utilisez drawElementImage.

<script>
  const ctx = document.getElementById('canvas').getContext('2d');

  canvas.onpaint = () => {
    ctx.reset();
    // Dessine l'élément de formulaire à la position 0,0
    let transform = ctx.drawElementImage(form_element, 0, 0);
    // ...
  };
</script>

Étape 3 — Mettre à jour la transformation de l'élément

Il est crucial de mettre à jour la propriété transform CSS de l'élément DOM chaque fois qu'il est repeint, afin que le navigateur sache où il se trouve sur l'écran pour l'interactivité et les fonctionnalités du navigateur.

<script>
  // ... (code précédent)
  canvas.onpaint = () => {
    // ... (code de rendu)
    form_element.style.transform = transform.toString();
  };
</script>

Étape 4 — Configurer correctement la taille du Canvas

Pour éviter le flou lors du rendu, il est important de faire correspondre la grille de pixels du Canvas au facteur d'échelle de l'appareil. Utilisez un ResizeObserver pour cela.

<script>
  // Redimensionne la grille du canvas pour correspondre au facteur d'échelle de l'appareil afin d'éviter le flou.
  const observer = new ResizeObserver(([entry]) => {
    canvas.width = entry.devicePixelContentBoxSize[0].inlineSize;
    canvas.height = entry.devicePixelContentBoxSize[0].blockSize;
  });
  observer.observe(canvas, { box: 'device-pixel-content-box' });
</script>

Rendu WebGL

Pour le rendu WebGL, la configuration initiale du Canvas et l'ajout du HTML sont les mêmes. La méthode de rendu change pour utiliser texElementImage2D.

<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
  <div> <h1> Je vais être rendu dans une texture WebGL! </h1> </div>
</canvas>

// code de configuration webgl

canvas.onpaint = () => {
  // code de configuration de la texture
  if (gl.texElementImage2D) {
    gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, uiElement);
  }
};

Rendu WebGPU

Pour le rendu WebGPU, la configuration initiale du Canvas et l'ajout du HTML sont également les mêmes. La méthode de rendu utilise copyElementImageToTexture.

<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
  <div> <h1> Je vais être rendu dans une texture WebGPU! </h1> </div>
</canvas>

// code de configuration WebGPU

canvas.onpaint = () => {
  root.device.queue.copyElementImageToTexture(valueElement, 512, 128, { texture: targetTexture });
};

Mise à jour de la transformation WebGL et WebGPU

La mise à jour de la transformation en 3D est plus complexe, car elle implique de mapper les espaces de coordonnées 3D aux espaces de coordonnées CSS.

// texElementImage2D utilisé ci-dessus
if (canvas.getElementTransform) {
  // 1. Convertir la matrice MVP (gl-matrix Float32Array) en DOMMatrix
  // 2. Pixels CSS de l'élément -> Espace Modèle WebGL
  // 3. Espace de découpe WebGL -> Pixels CSS du Canvas (Transformation du Viewport)
  // 4. Combiner: Viewport * Modèle
  const finalTransform = toCSSViewport.multiply(mvpDOM).multiply(toGLModel);

  const transform = canvas.getElementTransform(uiElement, finalTransform);
  if (transform) {
    uiElement.style.transform = transform.toString();
  }
}

Tableaux comparatifs

Caractéristique DOM (Document Object Model) Canvas (HTML5) HTML-in-Canvas API
Contenu Éléments HTML sémantiques Grille de pixels de bas niveau Éléments HTML sémantiques rendus sur Canvas
Layout Solutions de mise en page UI et texte intégrées Nécessite une logique complexe ou des frameworks Utilise les solutions de mise en page du DOM
Interactivité Entièrement interactif, accessible, recherchable Fonctionnalité de base, nécessite une logique complexe Entièrement interactif, accessible, recherchable
Intégrations Navigateur Accès complet (sélection de texte, clic droit, accessibilité, traduction, mode lecture, extensions, mode sombre, zoom, remplissage automatique) Aucune intégration native des fonctionnalités du navigateur Accès complet aux fonctionnalités du navigateur
Performance Peut être moins performant pour les graphiques 2D/3D complexes Accès bas niveau et performant pour les graphiques 2D/3D Combine la performance graphique avec la richesse du DOM
Complexité de développement Facile pour les UIs standards Complexe pour les UIs riches et le texte Simplifie l'intégration UI dans les scènes 2D/3D

Démonstrations et Cas d'Usage

Démonstrations et Cas d'Usage

Texte complexe dans un contexte 2D

L'API permet de rendre du texte avec des directions variées (droite-à-gauche, haut-en-bas), des images et des SVG animés directement dans un Canvas, tout en conservant la sélection de texte, le clic droit et l'interactivité.

Accessibilité

Même si le contenu est rendu dans un Canvas, les informations d'accessibilité sont exposées, permettant aux lecteurs d'écran et aux outils comme Lighthouse de comprendre et d'évaluer le contenu avec un score de 100%.

WebGL inspectable et modifiable dans les outils de développement

Les UIs rendues en WebGL restent entièrement interactives et peuvent être inspectées et modifiées en temps réel via les outils de développement du navigateur. Les changements dans le DOM se reflètent instantanément dans le rendu WebGL.

Respecte les modes sombre et clair

Si votre CSS est configuré pour respecter les préférences de mode sombre/clair du navigateur, l'UI rendue dans le Canvas s'adaptera automatiquement au thème choisi par l'utilisateur.

Panneau d'affichage et SVG animé

Il est possible de créer des éléments 3D complexes comme un panneau d'affichage avec des SVG animés rendus directement dans une texture WebGL, sans code supplémentaire pour l'animation, et en conservant l'interactivité du texte.

Superpositions visuellement époustouflantes avec la recherche dans la page

L'API permet de créer des superpositions visuellement impressionnantes sur des modèles 3D. Les éléments de l'interface utilisateur, comme les curseurs ou le texte, peuvent interagir avec le modèle 3D (par exemple, la réfraction) et les fonctionnalités de recherche dans la page continuent de fonctionner, mettant en évidence le texte à travers le modèle.

Effets amusants sur le texte

Des effets de distorsion de texte peuvent être appliqués en temps réel lors du survol de la souris. La sélection de texte fonctionne toujours, et l'effet s'applique à la sélection, démontrant la flexibilité de l'API avec le texte.

Livres 3D traduisibles dans n'importe quelle police

Créez des livres 3D avec des pages qui tournent, où le texte est rendu via HTML. Les utilisateurs peuvent changer la police du texte et, plus important encore, utiliser la fonctionnalité de traduction native du navigateur pour traduire le contenu du livre, même s'il est intégré dans une scène 3D.

Fonctionne avec les outils d'IA et les extensions

Étant donné que le contenu HTML est exposé dans l'arbre DOM, les outils d'IA, les robots d'indexation et les extensions de navigateur (comme les extracteurs de texte) peuvent interagir directement avec le texte rendu dans le Canvas, permettant des fonctionnalités avancées comme la lecture à voix haute ou l'extraction de données.

Éléments d'entrée dans WebGPU

Des éléments d'entrée complexes, comme un curseur "jelly slider" avec des effets visuels avancés, peuvent être rendus en WebGPU. Ces éléments restent entièrement interactifs et leurs propriétés peuvent être modifiées via les outils de développement, avec des mises à jour automatiques du rendu.

⚠️ Erreurs fréquentes et pièges

  1. Flou du rendu du Canvas : Ne pas ajuster la taille du Canvas au facteur d'échelle de l'appareil peut entraîner un rendu flou. Solution : Utilisez un ResizeObserver pour synchroniser canvas.width et canvas.height avec entry.devicePixelContentBoxSize. (voir Étape 4)
  2. Perte d'interactivité et de fonctionnalités du navigateur : Oublier de définir la propriété layoutsubtree sur la balise <canvas> empêche le navigateur de reconnaître le contenu HTML pour l'interactivité et l'accessibilité. Solution : Ajoutez layoutsubtree à votre balise <canvas>. (voir Étape 1)
  3. Transformations CSS non synchronisées : Si la transformation CSS de l'élément DOM n'est pas mise à jour après le rendu dans le Canvas, le navigateur ne saura pas où l'élément est positionné, ce qui perturbera l'interactivité. Solution : Appliquez la transformation retournée par la méthode de rendu (par exemple, drawElementImage) à la propriété style.transform de l'élément DOM. (voir Étape 3)
  4. Fuites de ressources ou comportement inattendu : Si vous arrêtez de peindre un élément dans le Canvas, mais ne le supprimez pas de l'arbre DOM, il continuera d'être exposé aux systèmes du navigateur comme s'il faisait partie de la page. Solution : Supprimez l'élément DOM du Canvas lorsque vous cessez de le peindre.

Glossaire

DOM (Document Object Model) : Interface de programmation pour les documents HTML et XML, représentant la structure d'une page web sous forme d'arbre d'objets.
Canvas : Élément HTML5 qui permet de dessiner des graphiques 2D et 3D via JavaScript, offrant un contrôle au niveau du pixel.
WebGL : API JavaScript pour le rendu de graphiques 3D interactifs et de graphiques 2D dans n'importe quel navigateur web compatible, sans l'utilisation de plug-ins.
WebGPU : API web de nouvelle génération pour les graphiques et le calcul, offrant un accès plus performant et plus moderne au GPU que WebGL.
layoutsubtree : Attribut expérimental de l'API HTML-in-Canvas qui indique au navigateur de considérer le contenu HTML imbriqué dans un Canvas comme faisant partie de l'arbre de rendu du DOM.

Points clés à retenir

  • L'API HTML-in-Canvas permet de fusionner la puissance des graphiques 2D/3D avec la richesse et l'interactivité du HTML standard.
  • Les UIs rendues via cette API conservent toutes les fonctionnalités natives du navigateur, y compris l'accessibilité, la traduction, la recherche dans la page et les modes sombre/clair.
  • La configuration de base implique l'ajout de l'attribut layoutsubtree au Canvas et l'utilisation de méthodes de rendu spécifiques au contexte (2D, WebGL, WebGPU).
  • Il est essentiel de synchroniser la transformation CSS de l'élément DOM avec sa position rendue dans le Canvas pour maintenir l'interactivité.
  • Des frameworks comme Three.js et PlayCanvas ont déjà intégré un support expérimental pour simplifier l'utilisation de l'API.
  • L'API est disponible en Origin Trial dans Chrome, permettant aux développeurs d'expérimenter son déploiement en production.
  • Cette technologie ouvre la voie à des applications web plus immersives et performantes, tout en respectant les standards d'accessibilité et les intégrations du navigateur.

Ressources

  • Explication de l'API HTML-in-Canvas : goo.gl/HIC-explainer
  • Guide de développement web moderne : goo.gl/HIC-MWG
  • Exemples de l'API HTML-in-Canvas : goo.gl/HIC-samples
  • Exemple Three.js avec HTML-in-Canvas : goo.gl/HIC-threejs-example
  • Dépôt Three.js : goo.gl/HIC-threejs
  • Exemple PlayCanvas avec HTML-in-Canvas : goo.gl/HIC-playcanvas-example
  • Dépôt PlayCanvas : goo.gl/HIC-playcanvas
  • Inscription à l'Origin Trial : goo.gl/HIC-OT
  • Partagez vos créations : goo.gl/awesome-HIC
  • Tous les liens centralisés : goo.gl/hic-central