Отрисовка HTML на 2D-холсте

HTML-in-Canvas API позволяет отрисовывать интерактивные и доступные поддеревья DOM непосредственно в контексте 2D-холста. Чтобы узнать больше об API и его преимуществах, прочитайте обзор HTML-in-Canvas.

В этом руководстве показано, как отобразить HTML на двухмерном холсте. Чтобы отрисовать HTML на 2D-холсте, выполните следующие действия:

  1. Подготовьте холст. Задайте нужные атрибуты, чтобы браузер знал, что HTML-код нужно отрисовать в элементе canvas. Эта настройка одинакова для контекстов 2D, WebGL и WebGPU. Узнайте, как настроить холст и как объявить элементы HTML, которые будут отрисовываться независимо.
  2. Нарисуйте изображение элемента на холсте.
  3. При необходимости синхронизируйте DOM и пиксели.

Рисование элементов HTML на холсте 2D

Когда холст будет готов, а элементы помечены как drawable, отрисуйте их в контексте 2D с помощью метода 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() поддерживает формы с 3, 5, 7 и 9 аргументами и принимает необязательный параметр options:

// 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);
Форма перегрузки Параметры Эффект макета
Размер по умолчанию (element, dx, dy) Элемент целиком в размере по умолчанию, верхний левый угол которого находится в точке (dx, dy).
Поле "Свой целевой сервис" (element, dx, dy, dwidth, dheight) Масштабирует полное изображение элемента в область просмотра dw × dh на холсте.
Обрезанное, размер по умолчанию (element, sx, sy, swidth, sheight, dx, dy) Только область swidth × sheight, начиная с (sx, sy), отрисованная в размере по умолчанию (в том же масштабе, что и форма по умолчанию).
Исходный фрагмент для назначения (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) Обрезает исходный элемент, начиная с (sx, sy) с размерами swidth × sheight, а затем сопоставляет его с целевым элементом (dx, dy, dwidth, dheight).

Синхронизация DOM и пикселей

Поскольку отрисовка <canvas> является императивной, а макет DOM и стили CSS – реактивными, браузеру нужен механизм, который будет синхронизировать отрисованные пиксели холста, интерактивные области проверки нажатия и деревья специальных возможностей. Прежде чем перейти к синхронизации DOM и пикселей, ознакомьтесь с событием paint, которое активируется, когда элементы DOM обновляются и их нужно перерисовать.

В контекстах 2D-холста браузер автоматически синхронизирует координаты макета элемента, границы специальных возможностей и проверку нажатия указателя с нарисованными координатами холста.

Как вручную изменить геометрию элемента

В сложных сценариях вы можете отключить автоматическую синхронизацию геометрии и управлять пространственными преобразованиями вручную. Передайте { preserveElementGeometry: true } в drawElementImage(), чтобы браузер не перезаписывал автоматически существующие координаты проверки нажатия элемента:

// 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 });
В 2D-режиме drawElementImage() обновляет эту геометрию автоматически. В этой демонстрации показано, как нарушается синхронизация геометрии, когда задано свойство { preserveElementGeometry: true }.

Дальнейшие действия