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:
- 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.
- Desenhe a imagem do elemento na tela.
- [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 });
drawElementImage() atualiza essa geometria automaticamente. Esta demonstração mostra como a geometria fica fora de sincronia quando { preserveElementGeometry: true } é definido.Próximas etapas
- Entenda os principais conceitos técnicos por trás do HTML-in-Canvas.
- Saiba como renderizar HTML em uma tela WebGL.
- Saiba como renderizar HTML em uma tela da WebGPU.
- Saiba mais sobre as estratégias de substituição.
- Registre um problema no GitHub para compartilhar seu feedback.
- Confira a coleção de demonstrações de HTML-in-Canvas da comunidade.