mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 12:54:29 +00:00
131 lines
5.5 KiB
Plaintext
131 lines
5.5 KiB
Plaintext
---
|
|
title: "HTML-in-Canvas"
|
|
description: "Render live HTML as WebGL textures — GPU shaders, 3D geometry, and cinematic effects on any DOM content."
|
|
---
|
|
|
|
# HTML-in-Canvas
|
|
|
|
The HTML-in-Canvas API (`drawElementImage`) lets you capture live, rendered DOM elements directly into a canvas at GPU speed. This means you can take any HTML — dashboards, forms, landing pages, app UIs — and render them as textures in WebGL scenes with shaders, 3D transformations, and post-processing effects.
|
|
|
|
<Warning>
|
|
**Chrome flag required.** The `drawElementImage` API is experimental and must be enabled manually:
|
|
|
|
1. Open `chrome://flags/#canvas-draw-element` in Chrome or Brave
|
|
2. Set **CanvasDrawElement** to **Enabled**
|
|
3. Restart the browser
|
|
|
|
HyperFrames enables this flag automatically during rendering (`--enable-features=CanvasDrawElement`), so rendered videos work without manual setup. The flag is only needed for live preview in the Studio.
|
|
</Warning>
|
|
|
|
## How it works
|
|
|
|
1. Place HTML content inside a `<canvas layoutsubtree>` element
|
|
2. The browser renders the HTML children as normal DOM
|
|
3. Call `ctx.drawElementImage(element, x, y, w, h)` to capture the rendered pixels into the canvas
|
|
4. Use the canvas as a Three.js texture, apply shaders, map to 3D geometry
|
|
|
|
```html
|
|
<!-- 1. HTML content lives inside the canvas -->
|
|
<canvas id="capture" layoutsubtree width="1920" height="1080">
|
|
<div class="my-dashboard">
|
|
<h1>Revenue: $4.2M</h1>
|
|
<div class="chart">...</div>
|
|
</div>
|
|
</canvas>
|
|
|
|
<!-- 2. WebGL canvas for 3D rendering -->
|
|
<canvas id="theater" width="1920" height="1080"></canvas>
|
|
```
|
|
|
|
```javascript
|
|
// 3. Capture HTML to canvas
|
|
var capCanvas = document.getElementById("capture");
|
|
var ctx = capCanvas.getContext("2d");
|
|
ctx.drawElementImage(capCanvas.querySelector(".my-dashboard"), 0, 0, 1920, 1080);
|
|
|
|
// 4. Use as Three.js texture
|
|
var texture = new THREE.CanvasTexture(capCanvas);
|
|
var material = new THREE.MeshBasicMaterial({ map: texture });
|
|
```
|
|
|
|
## What makes this different
|
|
|
|
Traditional approaches like `html2canvas` re-parse and re-render the DOM in JavaScript — they're slow, lossy, and miss CSS features like `backdrop-filter`, complex shadows, and web fonts. The `drawElementImage` API uses the browser's own compositor, so:
|
|
|
|
- **Pixel-perfect** — every CSS feature is supported because the browser renders it natively
|
|
- **GPU-accelerated** — captures at 60fps, fast enough for real-time animation
|
|
- **Live content** — the HTML can animate, scroll, and change between captures
|
|
- **Multiple captures simultaneously** — no nesting restrictions, multiple `<canvas layoutsubtree>` elements can capture different content in the same composition
|
|
|
|
## Feature detection
|
|
|
|
Always feature-detect before using the API. Compositions should fall back gracefully for browsers without the flag enabled.
|
|
|
|
```javascript
|
|
function isSupported() {
|
|
var tc = document.createElement("canvas");
|
|
if (!("layoutSubtree" in tc)) return false;
|
|
tc.setAttribute("layoutsubtree", "");
|
|
var ctx = tc.getContext("2d");
|
|
return ctx && typeof ctx.drawElementImage === "function";
|
|
}
|
|
|
|
if (isSupported()) {
|
|
ctx.drawElementImage(element, 0, 0, w, h);
|
|
} else {
|
|
// Fallback: draw text directly on canvas, use static image, etc.
|
|
}
|
|
```
|
|
|
|
## Re-capturing every frame
|
|
|
|
For animated content (scrolling, transitions, counters), call `drawElementImage` inside your render loop to update the texture every frame:
|
|
|
|
```javascript
|
|
function render() {
|
|
// Update HTML state
|
|
scrollContainer.style.transform = "translateY(-" + scrollOffset + "px)";
|
|
counterEl.textContent = Math.round(currentValue);
|
|
|
|
// Re-capture
|
|
ctx.clearRect(0, 0, W, H);
|
|
ctx.drawElementImage(htmlElement, 0, 0, W, H);
|
|
texture.needsUpdate = true;
|
|
|
|
// Render 3D scene with updated texture
|
|
renderer.render(scene, camera);
|
|
}
|
|
```
|
|
|
|
## Catalog blocks
|
|
|
|
Install all HTML-in-Canvas blocks at once:
|
|
|
|
```bash
|
|
npx hyperframes add html-in-canvas
|
|
```
|
|
|
|
Or install individually:
|
|
|
|
| Block | Description | Install |
|
|
|-------|-------------|---------|
|
|
| [iOS 26 Liquid Glass Home Screen](/catalog/blocks/ios26-liquid-glass) | iPhone home screen with live Liquid Glass notifications and widgets | `npx hyperframes add ios26-liquid-glass` |
|
|
| [macOS Tahoe Liquid Glass Desktop](/catalog/blocks/macos-tahoe-liquid-glass) | MacBook desktop with liquid glass windows, dock, and notifications | `npx hyperframes add macos-tahoe-liquid-glass` |
|
|
| [Liquid Glass Notification](/catalog/blocks/liquid-glass-notification) | Native-feeling glass notification stack with progress and reply states | `npx hyperframes add liquid-glass-notification` |
|
|
| [iPhone & MacBook](/catalog/blocks/vfx-iphone-device) | Real 3D GLTF devices with live HTML screens | `npx hyperframes add vfx-iphone-device` |
|
|
| [Text Cursor](/catalog/blocks/vfx-text-cursor) | Dramatic text reveal with chromatic shadows | `npx hyperframes add vfx-text-cursor` |
|
|
| [Portal](/catalog/blocks/vfx-portal) | Dimension breach with volumetric light | `npx hyperframes add vfx-portal` |
|
|
| [Shatter](/catalog/blocks/vfx-shatter) | HTML shatters into glass fragments | `npx hyperframes add vfx-shatter` |
|
|
| [Magnetic](/catalog/blocks/vfx-magnetic) | Magnetic field particle visualization | `npx hyperframes add vfx-magnetic` |
|
|
| [Liquid Background](/catalog/blocks/vfx-liquid-background) | Organic liquid simulation | `npx hyperframes add vfx-liquid-background` |
|
|
|
|
## Rendering
|
|
|
|
HyperFrames enables the Chrome flag automatically during rendering. No special configuration needed:
|
|
|
|
```bash
|
|
npx hyperframes render --output my-video.mp4
|
|
```
|
|
|
|
For Docker renders, the flag is also enabled automatically inside the container.
|