Heritiana Antonio Frond end Designer | Developer

Hello, I am

Heritiana Antonio

Frond end Designer | Developer

drawElementImage rend-il le texte d’un canvas sélectionnable ?

1 min de lecture

Carte claire posée sur un rectangle sombre, traversée d’une bande de sélection ambre, avec un curseur.

drawElementImage rend-il le texte d’un canvas sélectionnable ?

Depuis le 3 novembre 2026, Chrome 157 peut répondre oui. drawElementImage() peint dans le canvas le rendu d’un élément HTML déjà présent dans la page. Ce texte reste un nœud du document : on peut le surligner, le copier, le trouver avec la recherche du navigateur et le lire avec un lecteur d’écran. fillText() ne fait rien de tout cela. Le 9 novembre 2026, Firefox 159 et Safari 27.2 n’exposent pas la méthode. Un paragraphe laissé dans la balise canvas y reste invisible.

Un élément vivant, pas une image de lettres

drawElementImage() copie dans le bitmap du canvas l’image déjà peinte d’un élément marqué drawable. En contexte 2D, l’appel aligne aussi la zone de clic, le rectangle de sélection et les limites annoncées aux outils d’assistance sur l’endroit dessiné.

L’article Chrome for Developers du 26 octobre 2026 présente l’API comme livrée avec Chrome 157. Le canal stable du 3 novembre donne 157.0.8103.38 sur Linux, 157.0.8103.38 et .39 sur Windows et macOS. Le déploiement est progressif. Chrome pour Android reçoit 157.0.8103.38 ce jour-là, puis 157.0.8103.46 le 5 novembre. On teste la propriété, pas la date de l’annonce.

fillText() dépose des pixels : pas de sélection, pas d’arbre d’accessibilité, pas de résultat dans la recherche de la page. Du HTML posé par-dessus le canvas se sélectionne, puis se décale dès que la scène bouge. drawElementImage() garde le paragraphe dans le document et le peint dans le bitmap.

Le balisage minimal

Deux attributs préparent la page. content="drawable" sur le canvas demande au navigateur de mettre en page ses descendants, au lieu de les traiter seulement comme un contenu de repli caché. drawable sur un descendant en fait une racine de peinture. La méthode dessine cet élément et le sous-arbre qui ne porte pas lui-même drawable.

<canvas id="scene" content="drawable">
  <p id="note" drawable>Cette phrase reste un paragraphe.</p>
</canvas>
function supportsHtmlInCanvas() {
  const test = document.createElement("canvas");
  test.setAttribute("content", "drawable");
  return test.content === "drawable";
}

let scaleX = 1;
let scaleY = 1;
const canvas = document.getElementById("scene");
const note = document.getElementById("note");

if (supportsHtmlInCanvas()) {
  const ctx = canvas.getContext("2d");
  canvas.addEventListener("paint", () => {
    ctx.reset();
    ctx.drawElementImage(note, 24 * scaleX, 32 * scaleY);
  });
  canvas.requestPaint();
}

La détection est celle du guide conceptuel Chrome. Après setAttribute("content", "drawable"), canvas.content vaut "drawable" seulement si la valeur est reconnue. Le gestionnaire paint sert au premier dessin. Le navigateur l’émet aussi, comme CanvasPaintEvent, quand le texte, la mise en page ou le style d’un descendant drawable change. changedElements ne liste que ces éléments. requestPaint() en programme un même si le DOM n’a pas bougé.

Un style modifié dans paint n’apparaît qu’à l’image suivante. Les ordres de dessin comptent pour l’image en cours. Ce qui doit être visible tout de suite se prépare dans requestAnimationFrame. scaleX et scaleY passent des pixels CSS aux pixels de grille : sans eux, 24 vise 24 pixels de grille. On les laisse à 1 tant que l’observateur de taille n’a pas tourné.

Hors Chrome, le paragraphe disparaît

Un navigateur qui sait afficher un canvas n’affiche pas les enfants de cette balise comme du HTML ordinaire. Ce repli ne sert que si la balise elle-même est inconnue. Firefox et Safari connaissent canvas et ignorent content="drawable". La phrase reste dans le DOM et ne se voit pas. Le test doit la sortir.

if (!supportsHtmlInCanvas()) {
  canvas.after(note);
  canvas.hidden = true;
}

Can I Use, relu le 9 novembre 2026, coche drawElementImage pour Chrome 157 à 160, Chrome pour Android 157 et le navigateur Android 157. La part d’usage affichée ce jour-là est 44,08 %. La méthode est absente de Firefox 159, de Firefox 160 à 162, de Firefox pour Android 159, de Safari 27.2 et 27.3, d’Opera 139 et de Samsung Internet 31. La ligne Edge s’arrête à la version 156, encore sans la méthode. Ce tableau ne dit pas ce que fait Edge 157.

html2canvas et dom-to-image, cités par Chrome comme replis, photographient le DOM. Ce bitmap ne se sélectionne pas.

dx et dy comptent en pixels de grille

La page 2D, mise à jour le 23 octobre 2026, sépare les unités. dx, dy, dwidth et dheight sont des pixels de la grille, ceux de canvas.width et canvas.height. Le rectangle source, sx, sy, swidth et sheight, est en pixels CSS, comme offsetWidth et les coordonnées de pointeur. Mélanger les deux dans la forme à neuf arguments recadre la mauvaise zone, puis l’étire ailleurs.

Avec un devicePixelRatio de 2, un canvas de 400×200 pixels CSS a besoin d’une grille 800×400. Sinon le glyphe subit un anticrénelage dans le bitmap, puis un second lors de l’étirement. Le guide le montre avec 360×180 pixels CSS, une grille de 300×150 et un ratio de 1,5. Un ResizeObserver aligne la grille sur devicePixelContentBoxSize et pose scaleX à canvas.width / largeur CSS. Écrire width ou height efface le bitmap, même à valeur égale, et réinitialise le contexte 2D. L’observateur est suivi d’un paint dans la même image. Un autre changement de grille demande requestPaint().

Le dessin part de la boîte de bordure. Avec du padding et content-box, 200 px annoncés dépassent 200 px peints. border-box aligne les deux. Cinq arguments placent toute la carte dans un rectangle de la grille. Sept recadrent en pixels CSS sans changer l’échelle. Neuf recadrent, puis redimensionnent.

La sélection suit la géométrie

Voir la phrase ne suffit pas. Le clic, la sélection et l’anneau de focus vont à un élément dont la géométrie a été posée. En 2D, drawElementImage() le fait par défaut, à partir des arguments, du style calculé et de la transformation du contexte. Le surlignage tombe sur les lettres peintes, pas sur l’ancien emplacement du paragraphe.

preserveElementGeometry: true coupe cette mise à jour. Les pixels bougent, la zone cliquable non. On ne l’utilise que pour rappeler ensuite updateElementGeometry(), avec une DOMMatrix dans canvasTransform. Cette matrice est en pixels CSS. Une translation copiée depuis dx sans division par scaleX décale la sélection.

En WebGL et en WebGPU, rien n’est automatique. L’élément devient une texture, que le nuanceur peut placer n’importe où. Sans la matrice du dessin, les clics restent à l’ancien endroit pendant que la carte tourne. Un texte lisible dans la texture n’est pas sélectionnable au bon endroit.

Sans géométrie, l’élément reste lisible par un lecteur d’écran, mais sans limites : une loupe ne sait pas où le poser. clearElementGeometry() retire cette géométrie sans retirer le nœud du DOM. toDataURL(), toBlob() et captureStream() vont plus loin : le fichier ne contient plus que des pixels. La sélection vit dans la page.

Un second drawable n’est pas inclus

Un élément drawable capture ses descendants, sauf ceux qui portent aussi drawable. drawElementImage(carte) ne peint pas le bouton marqué à part. Sans le second appel, il manque dans l’image et n’a pas de zone de clic. Ce second appel le place ailleurs quand la carte se déplace. Chaque mise à jour de géométrie amène par défaut l’élément au sommet de la pile de clic. preserveHitTestOrder: true garde la priorité actuelle, pour redessiner un fond sans voler le bouton. Les canevas imbriqués se peignent en commençant par l’enfant, afin que le parent copie des pixels déjà à jour.

Questions fréquentes

fillText permet-il de sélectionner la phrase ?

Non. fillText() ne crée pas de nœud. Il n’y a rien à surligner, et la recherche de la page ne trouve pas la chaîne. Il faut un élément HTML dessiné avec drawElementImage(), une fois sa géométrie posée.

Firefox 159 affiche-t-il le texte placé dans le canvas ?

Non, pas au 9 novembre 2026. Can I Use ne donne pas drawElementImage à Firefox 159, ni à Safari 27.2 ou 27.3. Ces navigateurs connaissent canvas et masquent ses enfants. Il faut canvas.after() quand canvas.content ne vaut pas "drawable".

Pourquoi le texte est-il flou sur un écran à fort ratio ?

La grille ne coïncide pas avec les pixels physiques. Le glyphe subit deux anticrénelages. On aligne canvas.width et canvas.height sur devicePixelContentBoxSize, puis on convertit les pixels CSS avant dx et dy.

Le bouton drawable est-il dessiné avec sa carte ?

Non, s’il porte lui aussi drawable. Il forme une autre racine de peinture. Sans un second drawElementImage(), le trou est dans l’image et le clic n’a pas de zone.

Une image exportée garde-t-elle la sélection ?

Non. toDataURL() et toBlob() figent des pixels. La sélection concerne l’élément encore dans la page. En 3D, updateElementGeometry() doit en plus suivre le dessin.

Faut-il appeler updateElementGeometry en 2D ?

Pas par défaut. drawElementImage() pose la géométrie. On n’appelle updateElementGeometry() que si preserveElementGeometry: true a coupé cette pose, ou si le contexte est WebGL ou WebGPU.

Reprendre à côté du canvas

La sélection tient en trois tests : l’élément est du HTML, Chrome reconnaît content="drawable", et la géométrie suit le dessin. Pour revoir, à côté, le DOM, les événements et les modules qui portent ce script, les parcours sont sur la page Apprentissage. Les notes de ce genre restent dans la catégorie article. Pour faire relire un canvas déjà en production, le formulaire de la page Me contacter suffit.

Voir Egalement

My Blog