Renderizar HTML em uma tela 2D

A API HTML-in-Canvas permite renderizar subárvores DOM interativas e acessíveis diretamente em um contexto de tela 2D. Leia a visão geral da HTML-in-Canvas para saber mais sobre a API e os benefícios dela.

Este guia demonstra como renderizar HTML em uma tela 2D. Para renderizar HTML em uma tela 2D, siga estas etapas:

  1. Prepare sua tela. Defina os atributos certos de forma declarativa para que o navegador saiba que deve renderizar o HTML em uma tela. Essa configuração é idêntica nos contextos 2D, WebGL e WebGPU. Saiba como configurar sua tela e como declarar elementos HTML para serem desenhados de forma independente.
  2. Desenhe a imagem do elemento na tela.
  3. [Opcional] Sincronize o DOM e os pixels.

Desenhar elementos HTML em uma tela 2D

Quando a tela estiver pronta e os elementos forem marcados como drawable, renderize-os no contexto 2D usando o método drawElementImage().

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const childElement1 = document.getElementById("childElement1");
const childElement2 = document.getElementById("childElement2");

canvas.onpaint = () => {
  ctx.reset();
  // 1. Draw the primary element at coordinate (20, 20)
  ctx.drawElementImage(childElement1, 20, 20);
  // 2. Draw the secondary nested button at a custom offset
  ctx.drawElementImage(childElement2, 40, 90);
}

drawElementImage() é compatível com formas de 3, 5, 7 e 9 argumentos e aceita um parâmetro options opcional:

// 1. Basic position: (element, dx, dy, options?)
ctx.drawElementImage(targetElement, 100, 150);

// 2. Scaled / resized: (element, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 100, 150, 180, 60);

// 3. Cropped, default size: (element, sx, sy, swidth, sheight, dx, dy, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150);

// 4. Cropped and resized: (element, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150, 180, 60);
Formulário de sobrecarga Parâmetros Efeito de layout
Tamanho padrão (element, dx, dy) O elemento inteiro no tamanho padrão, com o canto superior esquerdo em (dx, dy).
Caixa de destino personalizado (element, dx, dy, dwidth, dheight) Dimensiona a imagem completa do elemento em uma janela de visualização de dw × dh na tela.
Cortada, tamanho padrão (element, sx, sy, swidth, sheight, dx, dy) Somente a área swidth × sheight que começa em (sx, sy), desenhada no tamanho padrão dessa área (a mesma escala do formulário de tamanho padrão).
Fatia de origem para destino (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) Corta o elemento de origem começando em (sx, sy) com as dimensões swidth × sheight e o mapeia para o destino (dx, dy, dwidth, dheight).

Sincronizar o DOM e os pixels

Como a renderização de <canvas> é imperativa, enquanto o layout do DOM e o estilo CSS são reativos, o navegador precisa de um mecanismo para manter sincronizados os pixels de tela renderizados, as regiões de teste de hit de interação e as árvores de acessibilidade. Antes de aprender a sincronizar o DOM e os pixels, entenda o evento paint que é acionado quando os elementos do DOM são atualizados e precisam ser redesenhados.

Em contextos de tela 2D, o navegador sincroniza automaticamente as coordenadas de layout do elemento, os limites de acessibilidade e o teste de hit do ponteiro com as coordenadas da tela desenhada.

Atualizar manualmente a geometria do elemento

Em cenários avançados, é possível desativar a sincronização automática de geometria e controlar as transformações espaciais manualmente. Transmita { preserveElementGeometry: true } para drawElementImage() para impedir que o navegador substitua automaticamente as coordenadas de teste de hit do elemento:

// 1. Draw the element without altering its existing hit-test bounds
ctx.drawElementImage(targetElement, elementX, 200, { preserveElementGeometry: true });

// 2. Construct a custom transform matrix as needed,
// assuming scaleX/scaleY = canvas grid pixels per CSS pixel,
// from your resize observer (see "Units and sizing").
const currentTransform = new DOMMatrix();
currentTransform.a = 1.5;          // scale X
currentTransform.e = x / scaleX;   // translate X: grid px → CSS px
currentTransform.f = y / scaleY;   // translate Y: grid px → CSS px

// 3. Explicitly apply the custom transform
canvas.updateElementGeometry(targetElement, { canvasTransform: currentTransform });
Em 2D, o drawElementImage() atualiza essa geometria automaticamente. Esta demonstração mostra como a geometria fica fora de sincronia quando { preserveElementGeometry: true } é definido.

Próximas etapas