HTML-in-Canvas в Chrome 157: интерактивный DOM в 2D, WebGL и WebGPU
- суббота, 31 октября 2026 г. в 00:00:06
Эта статья перевод оригинальной статьи «HTML-in-Canvas in Chrome 157: Interactive DOM inside 2D, WebGL, and WebGPU».
Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов и AI.
После успешного origin trial API HTML-in-Canvas официально вышел в стабильной версии Chrome 157. Он объединяет интерактивность и доступность DOM с производительностью и попиксельным управлением <canvas>. Так возможности браузера можно использовать вместе с графикой canvas, ускоренной на GPU.
Раньше при создании веб-приложений со сложной графикой приходилось выбирать между стандартными HTML-элементами и непосредственной работой с контекстами canvas.
Технология | Сильные стороны | Ограничения |
|---|---|---|
| Низкоуровневое управление пикселями с доступом к GPU для конвейеров 2D- и 3D-графики, собственных шейдеров и воркеров для внеэкранного рендеринга. Высокая производительность в тяжёлых интерфейсах с большим объёмом данных. | Нет встроенных возможностей веб-платформы: выделения, копирования и вставки текста, действий по правому клику и переноса строк. Непрозрачная для браузера сетка пикселей по умолчанию не поддерживает скринридеры, поиск по странице, автоматический перевод и автозаполнение. Для них нужна отдельная реализация. |
HTML | Семантический интерфейс со встроенными элементами форм, адаптивной типографикой и CSS-стилями. Интеграция со скринридерами, поиском по странице и DevTools. | Ограниченные возможности управления производительностью сложных интерфейсов. Визуальные эффекты ограничены стандартными CSS и SVG, без прямого управления пикселями или шейдеров. |
До появления этого API для интерфейсов, активно использующих canvas, было два подхода. У каждого были свои недостатки.
Отрисовка текста непосредственно в пикселях canvas с помощью fillText(). Приложение императивно рисовало текст и элементы управления как наборы пикселей. Это создавало несколько проблем:
Скринридеры и вспомогательные инструменты не могут прочитать пиксели canvas. Для доступности приходилось вручную создавать и синхронизировать невидимый резервный DOM.
Пользователь не мог искать текст через поиск по странице (Ctrl/Cmd+F), привычным образом копировать и вставлять его, вызывать контекстные меню, пользоваться переводом и проверкой правописания в браузере.
Для интернационализации приходилось включать в сборку большие JavaScript-движки компоновки текста.
HTML-элементы поверх canvas. Например, библиотеки размещали стандартные HTML-элементы над холстом, вычисляя ограничивающие прямоугольники и матричные преобразования в JavaScript. Здесь возникали другие проблемы:
Задержки синхронизации и визуальные разрывы. При прокрутке, масштабировании или движении камеры в 3D DOM-элементы могли смещаться или дрожать относительно пикселей canvas из-за разницы во времени подготовки кадров.
Ограничения обрезки и порядка наложения. HTML-слои всегда располагались поверх всего буфера canvas. Поместить HTML внутрь 3D-сцены, например за трёхмерный объект, внутрь стеклянного материала или в отражение зеркала, без сложных обходных решений с преобразованием iframe в изображение было нельзя.
Дополнительная нагрузка. Чтобы HTML-слои оставались на своих местах относительно canvas, на каждом кадре нужно пересчитывать преобразование каждого слоя в JavaScript и записывать его в style.transform. Перед отрисовкой браузер разбирает каждую строку и пересчитывает стиль элемента, поэтому каждый новый слой увеличивает работу основного потока. В 2D-контексте drawElementImage() обновляет положение элемента автоматически. В WebGL и WebGPU вычисленное преобразование передаётся в updateElementGeometry() как матрица. В обоих случаях браузеру не приходится разбирать CSS и пересчитывать стили.
HTML-in-Canvas устраняет необходимость в этих компромиссах. HTML внутри элемента <canvas> остаётся интерактивным, а интеграции с браузером работают автоматически.
HTML-содержимое внутри <canvas> сохраняет те же возможности, что и снаружи:
Компоновка и форматирование текста, включая многострочный и двунаправленный текст с CSS-стилями.
Элементы форм с широкими возможностями оформления через CSS и шейдеры.
Выделение, копирование и вставка текста, а также правый клик. Пользователи могут выделять текст внутри 3D-сцен и вызывать контекстные меню.
Доступность: HTML-содержимое canvas попадает в дерево доступности для скринридеров.
Функции браузера, включая перевод, автозаполнение и поиск по странице, работают без дополнительной настройки. Можно переводить и искать текст внутри текстур WebGL и WebGPU.
Расширения браузера тоже работают с этим содержимым. Например, расширение для замены текста автоматически обновляет текст на трёхмерных мешах.
В Chrome DevTools можно просматривать и менять CSS-стили элементов интерфейса внутри canvas.
Поисковые роботы и AI-агенты могут индексировать DOM-содержимое, отрисованное в 2D- и 3D-сценах.
Готовую композицию canvas с живыми DOM-элементами можно экспортировать в изображение (toDataURL(), toBlob()) или видеопоток (captureStream()).
Сравнение возможностей браузера при отрисовке текста непосредственно в canvas и через HTML-in-Canvas. В области HTML-in-Canvas текст можно выделять и переводить, а автозаполнение и другие функции браузера работают без дополнительной настройки. В области обычного canvas содержимое отрисовано методом fillText и не интерактивно.
API подходит для следующих задач:
Крупные приложения на canvas могут отрисовывать компоненты интерфейса прямо в рабочих областях холста, улучшая доступность и уменьшая размер сборки.
В 3D-сценах, играх и иммерсивных приложениях WebXR можно размещать интерактивные DOM-элементы прямо внутри сцены: например, внутриигровые терминалы или трёхмерные книги, которые можно читать.
Инструменты для создания и редактирования медиа могут сочетать HTML-типографику с шейдерными эффектами и экспортировать составные сцены непосредственно в изображения или видеопотоки.
Для выразительных интерфейсов можно обрабатывать HTML-содержимое как пиксели и создавать визуальные эффекты с помощью шейдеров.
Подробности есть в технической документации HTML-in-Canvas.
Для отрисовки HTML в canvas выполните следующие шаги.
Декларативно задайте атрибуты, которые сообщают браузеру, что HTML нужно отрисовывать в canvas. Эта настройка одинакова для контекстов 2D, WebGL и WebGPU. В документации описаны подготовка canvas и объявление HTML-элементов для независимой отрисовки.
<!-- Prepare your canvas by setting the `content` attribute --> <canvas id="canvas" width="600" height="400" content="drawable"> <!-- Mark child as `drawable` to render to canvas --> <div id="myElement" drawable> <!-- Your HTML here --> </div> </canvas>
Конкретная реализация зависит от контекста: 2D, WebGL или WebGPU.
const ctx = canvas.getContext("2d"); // Draw HTML element into canvas in 2D ctx.drawElementImage(myElement, myElementX, myElementY);
Синхронизация геометрии тоже зависит от контекста. В 2D браузер по умолчанию выполняет её автоматически. В 3D-контекстах нужно сформировать преобразование и передать его методу updateElementGeometry.
// In 3D, construct a transform as needed, for example: const transform = new DOMMatrix().translate(x, y); // Synchronize the element's DOM and pixels canvas.updateElementGeometry(myElement, { canvasTransform: transform });
HTML-in-Canvas поддерживают основные библиотеки для WebGL и трёхмерной графики.
Перечисленные инструменты являются сторонними проектами сообщества. Google и команда Chrome не разрабатывают, не сопровождают и официально не поддерживают их.
Three.js предоставляет экспериментальную поддержку через THREE.HTMLTexture.
const material = new THREE.MeshBasicMaterial(); material.map = new THREE.HTMLTexture(uiElement); const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material); scene.add(mesh);
PlayCanvas поддерживает потоковую передачу HTML-текстур через setSource().
canvas.addEventListener('paint', () => { htmlTexture.setSource(htmlElement); }, { once: true });
Babylon.js предоставляет встроенную привязку через BABYLON.HtmlTexture.
const htmlTexture = new BABYLON.HtmlTexture("htmlTexture", uiElement, scene); material.diffuseTexture = htmlTexture;
В PixiJS встроенная поддержка появилась в версии v8.19.0 благодаря HTMLSource.
import { HTMLSource } from 'pixi.js/html-source'; const sprite = Sprite.from(new HTMLSource({ resource: form, autoUpdate: true })); app.stage.addChild(sprite);
Библиотека компонентов CanvasUI с открытым исходным кодом создана специально для HTML-in-Canvas.
Подробности реализации смотрите в документации соответствующей библиотеки.
Для совместимости с разными браузерами проверяйте поддержку API перед выполнением кода:
export function supportsHtmlInCanvas() { if (typeof document === "undefined") return false; const canvas = document.createElement("canvas"); canvas.setAttribute("content", "drawable"); return canvas.content === "drawable"; }
Если API недоступен, можно использовать альтернативный интерфейс, HTML-слои поверх canvas или одну из готовых библиотек, например three-html-render, html2canvas или dom-to-image.
Эти библиотеки являются сторонними проектами сообщества. Google и команда Chrome не разрабатывают, не сопровождают и официально не поддерживают их.
Изучите полную документацию HTML-in-Canvas на Chrome for Developers.
Дополните возможности ассистентов для программирования с помощью Modern Web Guidance.
Поделитесь обратной связью в репозитории WICG на GitHub.
Посмотрите демонстрации HTML-in-Canvas от сообщества.