La API de HTML-in-Canvas te permite renderizar subárboles del DOM interactivos y accesibles directamente en un contexto de lienzo en 2D. Lee la descripción general de HTML-in-Canvas para obtener más información sobre la API y sus beneficios.
En esta guía, se muestra cómo renderizar HTML en un lienzo en 2D. Para renderizar HTML en un lienzo 2D, se deben seguir estos pasos:
- Prepara tu lienzo. Establecer de forma declarativa los atributos correctos para que el navegador sepa que debe renderizar HTML en un lienzo Esta configuración es idéntica en los contextos de 2D, WebGL y WebGPU. Obtén más información para configurar tu lienzo y declarar elementos HTML que se dibujarán de forma independiente.
- Dibuja la imagen del elemento en el lienzo.
- Sincroniza el DOM y los píxeles (opcional).
Dibuja elementos HTML en un lienzo 2D
Una vez que el lienzo esté listo y los elementos estén marcados como drawable, renderízalos en el contexto 2D con el 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() admite formas de 3, 5, 7 y 9 argumentos, y acepta un 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);
| Formulario de sobrecarga | Parámetros | Efecto de diseño |
|---|---|---|
| Tamaño predeterminado | (element, dx, dy) |
Todo el elemento en su tamaño predeterminado, con la esquina superior izquierda en (dx, dy). |
| Cuadro de destino personalizado | (element, dx, dy, dwidth, dheight) |
Ajusta la escala de la imagen completa del elemento a un viewport de dw × dh en el lienzo. |
| Recortado, tamaño predeterminado | (element, sx, sy, swidth, sheight, dx, dy) |
Solo el área swidth × sheight que comienza en (sx, sy), dibujada en el tamaño predeterminado de esa área (la misma escala que la forma de tamaño predeterminado). |
| Porción de origen al destino | (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) |
Recorta el elemento de origen a partir de (sx, sy) con las dimensiones swidth × sheight y, luego, lo asigna al destino (dx, dy, dwidth, dheight). |
Sincroniza el DOM y los píxeles
Debido a que la renderización de <canvas> es imperativa, mientras que el diseño del DOM y el estilo de CSS son reactivos, el navegador necesita un mecanismo para mantener sincronizados los píxeles del lienzo renderizado, las regiones de prueba de posicionamiento interactiva y los árboles de accesibilidad. Antes de aprender a sincronizar el DOM y los píxeles, asegúrate de comprender el evento paint que se activa cuando los elementos del DOM se actualizan y se deben volver a dibujar.
En los contextos de lienzo en 2D, el navegador sincroniza automáticamente las coordenadas de diseño del elemento, los límites de accesibilidad y las pruebas de posicionamiento del puntero con las coordenadas del lienzo dibujado.
Actualiza manualmente la geometría de los elementos
En situaciones avanzadas, puedes inhabilitar la sincronización automática de la geometría y controlar las transformaciones espaciales de forma manual. Pasa { preserveElementGeometry: true } a drawElementImage() para evitar que el navegador anule automáticamente las coordenadas de prueba de posicionamiento existentes del 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() actualiza esta geometría automáticamente. En esta demostración, se muestra cómo la geometría se desincroniza cuando se establece { preserveElementGeometry: true }.Próximos pasos
- Comprende los conceptos técnicos básicos de HTML-in-Canvas.
- Obtén información para renderizar HTML en un lienzo de WebGL.
- Obtén más información para renderizar HTML en un lienzo de WebGPU.
- Obtén más información sobre las estrategias de resguardo.
- Informa un problema en GitHub para compartir tus comentarios.
- Consulta la colección de demostraciones de HTML-in-Canvas de la comunidad.