HTML-in-Canvas API: полное руководство 2026 — рендеринг DOM на Canvas
Техническое руководство · 21 мая 2026

HTML-in-Canvas API:
полное руководство по рендерингу DOM на Canvas

Google анонсировала HTML-in-Canvas на Google I/O 2026 — новый API веб-платформы, позволяющий разработчикам рендерить реальные живые DOM-элементы прямо на HTML Canvas. Полное руководство с примерами кода и стратегиями внедрения.

Олег Максимов 21 мая 2026 20 мин чтения

Введение

Более десятилетия веб-разработчики сталкивались с неудобным выбором: строить в DOM (богатая интерактивность, доступность, стилизация) или на Canvas (полный контроль пикселей, высокая производительность, 3D-графика). Нельзя было получить и то, и другое — по крайней мере, элегантно. Решения вроде html2canvas и rasterizeHTML делали приблизительные скриншоты, но были медленными, неточными и не справлялись с динамическим контентом.

На Google I/O 2026 (19 мая) Google анонсировала HTML-in-Canvas — новый API веб-платформы, который наконец устраняет этот разрыв. Он позволяет рендерить реальные, живые DOM-элементы прямо на HTML Canvas, поддерживая 2D-, WebGL- и WebGPU-пайплайны. О других 15 обновлениях Chrome, анонсированных на I/O, читайте в нашем обзоре обновлений Chrome на Google I/O 2026.

API доступен как Origin Trial в Chrome 148-150 (стабильный канал, май 2026). Разработчики могут присоединиться через токен Origin Trial или включить флаг chrome://flags/#canvas-draw-element. Это руководство охватывает все примитивы API с рабочими примерами кода, таймлайном поддержки браузеров, стратегиями оптимизации производительности и реальными сценариями использования.

Решаемая проблема

До HTML-in-Canvas, если вы хотели использовать богатый интерактивный HTML — стилизованные формы, сложные макеты, живые визуализации данных — внутри Canvas-приложения (игра, дизайн-инструмент, видео-редактор), у вас было три плохих варианта:

HTML-in-Canvas API решает всё это, предоставляя прямой канал от браузерного рендерера DOM в ваш canvas-контекст. Это не скриншот — это сам браузерный движок рендеринга, рисующий на вашем canvas на уровне пикселей.

Основные концепции API

API состоит из нескольких примитивов, работающих вместе. Все методы находятся на интерфейсах HTMLCanvasElement, CanvasRenderingContext2D, WebGLRenderingContext и GPUCanvasContext.

layoutSubtree(element)

Перед тем как отрендерить DOM-элемент на canvas, браузер должен вычислить его макет. layoutSubtree() выполняет синхронный layout поддерева элемента, гарантируя, что все размеры, позиции и вычисленные стили готовы. Это обязательный первый шаг — вызов drawElementImage() или texElementImage2D() без предварительного layoutSubtree() даст пустой результат.

drawElementImage(element, dx, dy)

Рисует DOM-элемент на 2D canvas-контексте. Сигнатура повторяет drawImage() — можно задать координаты назначения и опционально исходную область кадрирования. Элемент рендерится в своём естественном DOM-размере.

texElementImage2D(element, textureUnit)

Загружает DOM-элемент напрямую как WebGL- или WebGPU-текстуру. Это самый эффективный путь для 3D-рендеринга — данные идут напрямую от браузерного композитора в память GPU, минуя CPU.

copyElementImageToTexture(element, texture)

Копирует отрендеренный DOM-элемент в существующий WebGL-текстурный объект. Полезно для фреймворков вроде Three.js, где вы управляете текстурными объектами напрямую.

captureElementImage(element)

Возвращает статичный ImageBitmap или HTMLImageElement отрендеренного элемента. Полезно для одноразовых захватов, где не нужны живые обновления.

getElementTransform(element)

Возвращает DOMMatrix, представляющую текущее вычисленное преобразование элемента относительно системы координат canvas. Критически важно для сопоставления координат Canvas и DOM, а также для применения трансформаций в 3D-сценах.

Событие Paint

Событие paint срабатывает на canvas, когда HTML-in-Canvas рендер завершён. Слушайте его, чтобы узнать, когда элемент отрисован и готов к использованию:

canvas.addEventListener('paint', () => {
  // Элемент отрисован — можно читать, композитировать и т.д.
});

ElementImage

Объект ElementImage представляет кешированный, готовый к рендеру снимок DOM-элемента. Создаётся через canvas.createElementImage(element) для эффективного повторного рендеринга без перевычисления layout на каждом кадре.

Примеры кода

1. 2D Canvas — рендеринг стилизованной HTML-формы

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const form = document.getElementById('loginForm');

// Шаг 1: Вычисляем layout
canvas.layoutSubtree(form);

// Шаг 2: Рисуем элемент на canvas
drawElementImage(form, 50, 50);

// Ожидаем завершения отрисовки
canvas.addEventListener('paint', () => {
  console.log('Форма отрисована на canvas!');
}, { once: true });

2. WebGL — элемент как текстура шейдера

const gl = canvas.getContext('webgl');
const uiElement = document.getElementById('hud-panel');

// Вычисляем layout
canvas.layoutSubtree(uiElement);

// Загружаем напрямую как текстурный юнит 0
texElementImage2D(uiElement, 0);

// Теперь доступна как TEXTURE0 в шейдере
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, myTexture);

3. Интеграция с Three.js — THREE.HTMLTexture

import * as THREE from 'three';

// Создаём внеэкранный HTML-контент
const div = document.createElement('div');
div.innerHTML = '<h2>Привет, 3D!</h2><p>Отрендерено через HTML-in-Canvas</p>';
div.style.cssText = 'width:300px;height:200px;background:#1a1a2e;color:white;padding:20px;';
document.body.appendChild(div);

// Вычисляем layout и захватываем
canvas.layoutSubtree(div);
const imageBitmap = captureElementImage(div);

// Создаём Three.js текстуру
const texture = new THREE.CanvasTexture(imageBitmap);
const material = new THREE.MeshStandardMaterial({ map: texture });
const mesh = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), material);
scene.add(mesh);

4. Матричная математика — getElementTransform на практике

const transform = canvas.getElementTransform(myElement);
// Возвращает DOMMatrix

// Применяем к Three.js объекту
const matrix = new THREE.Matrix4();
matrix.fromArray(transform.toFloat64Array());
threeObject.applyMatrix4(matrix);

// Или используем для hit-testing координат Canvas обратно в DOM:
canvas.addEventListener('click', (e) => {
  const inverse = transform.inverse();
  const domPoint = inverse.transformPoint(
    new DOMPoint(e.offsetX, e.offsetY)
  );
});

Element-Scoped View Transitions

Анонсированные вместе с HTML-in-Canvas на Google I/O 2026, element-scoped view transitions позволяют делать плавные анимированные переходы между состояниями DOM, когда эти элементы рендерятся на Canvas. Без этого изменения состояния DOM-элемента приводили бы к визуальному разрыву на Canvas.

const transition = document.startViewTransition({
  update: () => {
    // Меняем DOM-контент
    updateElementContent();
    // Перерендериваем для canvas
    canvas.layoutSubtree(myElement);
    drawElementImage(myElement, 0, 0);
  }
});

await transition.finished;
console.log('Плавный Canvas-переход завершён!');

Поддержка браузеров

Важно: Ни один другой браузерный движок (Firefox, Safari) не обязался реализовать HTML-in-Canvas. Это Chrome-эксклюзив на обозримое будущее. О других AI-функциях браузера читайте в руководстве по Chrome Prompt API.

Производительность и лучшие практики

1. Минимизируйте вызовы layoutSubtree()

layoutSubtree() — самая дорогая операция. Вызывайте её только при реальном изменении DOM. Для анимаций на 60fps, где DOM статичен, вызовите один раз и используйте кешированный ElementImage для последующих кадров.

2. Слушайте событие Paint

Не читайте пиксели canvas и не композитируйте сразу после drawElementImage(). Дождитесь события paint — оно сигнализирует о завершении рендеринга элемента на canvas.

3. Всегда учитывайте DPR

const dpr = window.devicePixelRatio || 1;
canvas.width = canvas.clientWidth * dpr;
canvas.height = canvas.clientHeight * dpr;
ctx.scale(dpr, dpr);

4. Feature Detection

const supportsHtmlInCanvas =
  'layoutSubtree' in HTMLCanvasElement.prototype &&
  'drawElementImage' in CanvasRenderingContext2D.prototype;

if (supportsHtmlInCanvas) {
  // Используем API
} else {
  // Падаем на традиционный Canvas или наложенный DOM
}

5. Используйте ElementImage для повторяющихся рендеров

const elementImage = canvas.createElementImage(hudElement);
canvas.layoutSubtree(hudElement);

function renderFrame() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  elementImage.draw(ctx, 10, 10);  // Быстрый путь — без DOM layout
  requestAnimationFrame(renderFrame);
}

Реальные сценарии использования

Игровые интерфейсы

Игровые движки, встроенные в браузер (PlayCanvas, Unity WebGL, кастомные), нуждаются в богатых меню, инвентарях, чатах и HUD. Вместо перерисовки каждого виджета на Canvas разработчики могут строить UI на стандартном HTML/CSS и рендерить его в игровой мир. Интеграция с Three.js делает это особенно простым для WebGL-движков.

Интерактивная визуализация данных

Инструменты визуализации данных часто смешивают Canvas-рендер графиков с DOM-тултипами, легендами и контролами. HTML-in-Canvas позволяет рендерить подсказки и аннотации как настоящие HTML-элементы прямо на Canvas, сохраняя их стилизацию и макет.

Дизайн-инструменты

Приложения вроде Figma, Photopea и Excalidraw рендерят всё на Canvas для производительности, но нуждаются в богатом текстовом редактировании, стилизованных инпутах и сложных контролах форм. HTML-in-Canva позволяет им встраивать реальные DOM-элементы (текстовые редакторы, палитры цветов, выпадающие списки) без хаков с оверлейным позиционированием.

Видео-редакторы и моушн-графика

Canvas-видео-редакторы могут композитировать DOM-элементы (титры, нижние трети, бегущие строки) прямо в свой рендер-пайплайн, используя WebGL-текстуры для GPU-ускорения.

WebGL vs WebGPU

Стратегия миграции

  1. Аудит текущего Canvas-рендеринга — какие элементы можно заменить DOM?
  2. Создать DOM-эквиваленты в скрытом offscreen-контейнере.
  3. Заменить Canvas draw-вызовы на layoutSubtree() + drawElementImage().
  4. Добавить слушатели paint event для синхронизации кадров.
  5. Реализовать сопоставление координат через getElementTransform().
  6. Оптимизировать с ElementImage для статичных элементов.
  7. Добавить fallback для браузеров без поддержки.

Ограничения

FAQ

Что такое HTML-in-Canvas API?
HTML-in-Canvas API — это новая функция веб-платформы Chrome, позволяющая разработчикам рендерить реальные живые DOM-элементы прямо на HTML Canvas. Вы вызываете layoutSubtree() для подготовки элемента, затем drawElementImage() (2D) или texElementImage2D() (WebGL/WebGPU) для отрисовки на контексте canvas.
Какие браузеры поддерживают HTML-in-Canvas?
По состоянию на май 2026 года — только Chrome 148-150 (Origin Trial). Ни Firefox, ни Safari не заявили о намерении реализовать этот API.
В чём разница между drawElementImage и texElementImage2D?
drawElementImage() рендерит на 2D-контекст. texElementImage2D() загружает напрямую как WebGL-текстуру, что эффективнее для 3D.
Работает ли HTML-in-Canvas с Three.js?
Да. THREE.HTMLTexture позволяет применять HTML-контент как карту материала к любому 3D-объекту — без скриншотов и предварительного рендеринга.
Как HTML-in-Canvas связан с element-scoped view transitions?
Element-scoped view transitions позволяют делать плавные анимированные переходы между состояниями DOM-элементов на Canvas, обеспечивая crossfade без мерцания.
Можно ли использовать HTML-in-Canvas в real-time приложениях?
Да, при правильной оптимизации: layoutSubtree() только при изменении DOM, использование paint event, правильное DPR-масштабирование и ElementImage для статичных элементов.
Могут ли пользователи кликать по HTML, отрендеренному на Canvas?
Напрямую — нет. Нужно вручную перенаправлять координаты Canvas в DOM через getElementTransform(). Исходный DOM-элемент остаётся интерактивным.

Стоит ли внедрять HTML-in-Canvas сейчас?

Если вы строите Canvas-приложение и нуждаетесь в богатых HTML-интерфейсах внутри него — да, но с оговорками. Origin Trial даёт возможность экспериментировать и предоставлять обратную связь. Для продакшн-приложений с широкой аудиторией дождитесь стабильного релиза. Всегда реализуйте graceful degradation.

Сочетание HTML-in-Canvas, element-scoped view transitions и других обновлений веб-платформы (см. наше руководство по WebMCP) делает это время захватывающим для веб-графики. Разрыв между «тем, что можно построить на DOM» и «тем, что можно на Canvas» наконец сокращается.

Контакты

Нужна помощь с Canvas-разработкой?

Я full-stack веб-разработчик, специализирующийся на Canvas, WebGL и высокопроизводительных веб-приложениях. Если вы планируете внедрять HTML-in-Canvas, давайте обсудим ваш проект.