pixijs-html-source

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
HTMLSource
and
ElementImageSource
turn a DOM element into a
TextureSource
you can use anywhere a normal texture works: on a
Sprite
, as a
Texture
frame, or mapped onto a
Mesh
.
HTMLSource
mirrors a live element's pixels into the GPU (the element stays editable and clickable in the browser);
ElementImageSource
wraps an immutable snapshot that never repaints. Both require a side-effect
import 'pixi.js/html-source'
to register their extensions.
These sources rely on the experimental HTML-in-Canvas browser proposal and are marked EXPERIMENTAL in PixiJS v8. The browser API must be enabled or the texture uploader throws on first render; feature-detect with
canvas.requestPaint
before relying on it. The API may change between minor releases.
Assumes familiarity with
pixijs-scene-sprite
and textures. These are texture sources, not display objects: wrap them in a
Sprite
(or
Texture
/
Mesh
) to put them on screen. Not available in Web Workers; a worker has no DOM to capture.
HTMLSource
ElementImageSource
可将DOM元素转换为
TextureSource
,你可以在任何普通纹理适用的场景使用它:比如在
Sprite
上、作为
Texture
帧,或是映射到
Mesh
上。
HTMLSource
会将实时元素的像素镜像到GPU中(该元素在浏览器中仍保持可编辑和可点击状态);
ElementImageSource
则封装一个不可变的快照,不会进行重绘。两者都需要导入副作用模块
import 'pixi.js/html-source'
来注册其扩展。
这些源依赖于实验性的HTML-in-Canvas浏览器提案,在PixiJS v8中被标记为EXPERIMENTAL。必须启用浏览器API,否则纹理上传器会在首次渲染时抛出错误;在使用前请通过
canvas.requestPaint
进行特性检测。该API可能在小版本更新中发生变化。
本文假设你已熟悉
pixijs-scene-sprite
和纹理相关知识。这些是纹理,而非显示对象:需要将它们包装在
Sprite
(或
Texture
/
Mesh
)中才能显示在屏幕上。Web Workers中无法使用此功能;因为Worker没有可捕获的DOM。

Quick Start

快速开始

ts
import "pixi.js/html-source";
import { Application, Sprite } from "pixi.js";
import { HTMLSource } from "pixi.js/html-source";

const app = new Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);

// The element must be a direct child of the Pixi canvas.
const form = document.createElement("form");
form.innerHTML = '<input value="still editable" />';
app.canvas.appendChild(form);

// Render the live form as a sprite. It stays interactive in the browser.
const source = new HTMLSource({ resource: form });
const sprite = Sprite.from(source);

sprite.anchor.set(0.5);
sprite.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(sprite);
Related skills:
pixijs-scene-sprite
(display the texture),
pixijs-scene-mesh
(map onto geometry,
PerspectiveMesh
),
pixijs-scene-dom-container
(the opposite: overlay HTML above the canvas, outside the GPU pipeline),
pixijs-assets
(texture sources vs the loader/cache),
pixijs-environments
(no DOM in Web Workers).
ts
import "pixi.js/html-source";
import { Application, Sprite } from "pixi.js";
import { HTMLSource } from "pixi.js/html-source";

const app = new Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);

// 元素必须是Pixi画布的直接子元素。
const form = document.createElement("form");
form.innerHTML = '<input value="still editable" />';
app.canvas.appendChild(form);

// 将实时表单渲染为精灵。它在浏览器中仍保持交互性。
const source = new HTMLSource({ resource: form });
const sprite = Sprite.from(source);

sprite.anchor.set(0.5);
sprite.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(sprite);
相关技能:
pixijs-scene-sprite
(显示纹理)、
pixijs-scene-mesh
(映射到几何体,如
PerspectiveMesh
)、
pixijs-scene-dom-container
(相反操作:在画布上方叠加HTML,脱离GPU管线)、
pixijs-assets
(纹理源与加载器/缓存的对比)、
pixijs-environments
(Web Workers中无DOM)。

Constructor options

构造函数选项

Both sources extend
TextureSource
, so all
TextureSourceOptions
(
resolution
,
scaleMode
,
addressMode
,
label
, etc.) are valid.
resource
is required on each.
HTMLSourceOptions
(live element):
OptionTypeDefaultDescription
resource
Element
Required. The live DOM element to render. Must be a direct child of the owning canvas, or the constructor throws.
canvas
HTMLSourceCanvas
The canvas that owns the element's layout subtree. Inferred from
resource.parentElement
when the element is a direct canvas child; pass it when inference is not possible.
autoLayout
boolean
true
Set the
layoutsubtree
attribute on the owning canvas. The browser only lays out and paints canvas children when it is present. Set
false
if you write
<canvas layoutsubtree>
yourself.
autoUpdate
boolean
true
Listen for the canvas
paint
event and re-upload when the element repaints. Set
false
for a static, captured-once texture.
autoRequestPaint
boolean
true
Request one initial paint after construction. Set
false
and call
source.requestPaint()
yourself each frame for continuous animation.
ElementImageSourceOptions
(immutable snapshot):
OptionTypeDefaultDescription
resource
ElementImage
Required. A snapshot from
canvas.captureElementImage(element)
.
autoClose
boolean
false
Call
snapshot.close()
when the source is destroyed. Leave
false
when the snapshot is shared with other sources, or you risk a use-after-free.
两个源都继承自
TextureSource
,因此所有
TextureSourceOptions
resolution
scaleMode
addressMode
label
等)均有效。每个源都必须指定
resource
参数。
HTMLSourceOptions
(实时元素):
选项类型默认值描述
resource
Element
必填项。要渲染的实时DOM元素。必须是所属画布的直接子元素,否则构造函数会抛出错误。
canvas
HTMLSourceCanvas
拥有元素布局子树的画布。当元素是画布的直接子元素时,会从
resource.parentElement
自动推断;无法推断时请手动传入。
autoLayout
boolean
true
在所属画布上设置
layoutsubtree
属性。只有存在该属性时,浏览器才会对画布子元素进行布局和绘制。如果你自己编写了
<canvas layoutsubtree>
,请设置为
false
autoUpdate
boolean
true
监听画布的
paint
事件,当元素重绘时重新上传纹理。如果需要静态的、仅捕获一次的纹理,请设置为
false
autoRequestPaint
boolean
true
构造完成后请求一次初始绘制。如果需要连续动画,请设置为
false
并在每一帧自行调用
source.requestPaint()
ElementImageSourceOptions
(不可变快照):
选项类型默认值描述
resource
ElementImage
必填项。来自
canvas.captureElementImage(element)
的快照。
autoClose
boolean
false
当源被销毁时调用
snapshot.close()
。如果快照与其他源共享,请保持
false
,否则可能会出现使用已释放资源的问题。

Core Patterns

核心模式

Setup and the side-effect import

设置与副作用导入

ts
import "pixi.js/html-source";
import { HTMLSource, ElementImageSource } from "pixi.js/html-source";
pixi.js/html-source
calls
extensions.add(...)
to register
HTMLSource
,
ElementImageSource
, and their WebGL/WebGPU uploaders. Without it, the renderer has no
'html'
uploader and these sources never render. The classes are exported from
pixi.js/html-source
, not
pixi.js
.
Importing a named export from
pixi.js/html-source
also triggers the side effect, so a bare
import 'pixi.js/html-source'
is only needed when you don't import anything else from that path.
ts
import "pixi.js/html-source";
import { HTMLSource, ElementImageSource } from "pixi.js/html-source";
pixi.js/html-source
会调用
extensions.add(...)
来注册
HTMLSource
ElementImageSource
及其WebGL/WebGPU上传器。如果不导入它,渲染器将没有
'html'
上传器,这些源也无法渲染。相关类从
pixi.js/html-source
导出,而非
pixi.js
pixi.js/html-source
导入命名导出也会触发副作用,因此只有当你不从该路径导入其他内容时,才需要单独导入
import 'pixi.js/html-source'

Feature detection and browser support

特性检测与浏览器支持

The HTML-in-Canvas API is gated behind a browser flag. Feature-detect before relying on it:
ts
import type { HTMLSourceCanvas } from "pixi.js/html-source";

const canvas = app.canvas as HTMLSourceCanvas;

if (canvas.requestPaint) {
  // HTML-in-Canvas is available.
}
Cast
app.canvas
to
HTMLSourceCanvas
for the typed
requestPaint
and
captureElementImage
members.
source.requestPaint()
returns
false
when the browser lacks the API; the texture uploader throws on first render when it is disabled.
HTML-in-Canvas API受浏览器标志限制。在使用前请先进行特性检测:
ts
import type { HTMLSourceCanvas } from "pixi.js/html-source";

const canvas = app.canvas as HTMLSourceCanvas;

if (canvas.requestPaint) {
  // HTML-in-Canvas可用。
}
app.canvas
转换为
HTMLSourceCanvas
类型,以获取带类型的
requestPaint
captureElementImage
成员。当浏览器不支持该API时,
source.requestPaint()
会返回
false
;如果API被禁用,纹理上传器会在首次渲染时抛出错误。

Live element with HTMLSource

使用HTMLSource渲染实时元素

ts
const form = document.createElement("form");
app.canvas.appendChild(form); // direct child of the canvas

const source = new HTMLSource({ resource: form });
const sprite = Sprite.from(source);
The element must be a direct child of the renderer's
<canvas>
; the source infers the owning canvas from
resource.parentElement
(or pass
canvas
). With the defaults, it sets
layoutsubtree
on the canvas, listens for the canvas
paint
event, and requests one initial paint.
source.isReady
is
false
until that first paint lands, then
true
.
resourceWidth
/
resourceHeight
report the element's real-pixel size (
offsetWidth
/
offsetHeight
).
ts
const form = document.createElement("form");
app.canvas.appendChild(form); // 画布的直接子元素

const source = new HTMLSource({ resource: form });
const sprite = Sprite.from(source);
元素必须是渲染器
<canvas>
的直接子元素;源会从
resource.parentElement
推断所属画布(或者手动传入
canvas
参数)。默认情况下,它会在画布上设置
layoutsubtree
,监听画布的
paint
事件,并请求一次初始绘制。在首次绘制完成前
source.isReady
false
,之后变为
true
resourceWidth
/
resourceHeight
会返回元素的实际像素尺寸(
offsetWidth
/
offsetHeight
)。

Continuous animation with requestPaint

使用requestPaint实现连续动画

ts
const source = new HTMLSource({ resource: clock, autoRequestPaint: false });
const sprite = Sprite.from(source);

app.ticker.add(() => {
  clock.textContent = new Date().toLocaleTimeString();
  source.requestPaint(); // re-snapshot the DOM this frame
});
The browser only repaints canvas children on demand. For an element whose content changes every frame, set
autoRequestPaint: false
and call
source.requestPaint()
in your own ticker to drive repaints on your schedule.
ts
const source = new HTMLSource({ resource: clock, autoRequestPaint: false });
const sprite = Sprite.from(source);

app.ticker.add(() => {
  clock.textContent = new Date().toLocaleTimeString();
  source.requestPaint(); // 本帧重新快照DOM
});
浏览器仅会按需重绘画布子元素。对于内容每一帧都变化的元素,请设置
autoRequestPaint: false
,并在自己的ticker中调用
source.requestPaint()
来按你的计划驱动重绘。

Immutable snapshot with ElementImageSource

使用ElementImageSource渲染不可变快照

ts
import { ElementImageSource } from "pixi.js/html-source";
import type { HTMLSourceCanvas } from "pixi.js/html-source";

const canvas = app.canvas as HTMLSourceCanvas;
const snapshot = canvas.captureElementImage!(element);

const source = new ElementImageSource({ resource: snapshot, autoClose: true });
const sprite = Sprite.from(source);
captureElementImage()
freezes an element's current pixels into an immutable
ElementImage
. There is no owning canvas, no
paint
listener, and no repaint lifecycle, so the source is ready the moment it is constructed. Reach for it when you need a frozen copy that outlives its element or is transferred around (transitions, "shatter" or trail effects). Release the snapshot with
snapshot.close()
when done, or pass
autoClose: true
to let the source close it on
destroy()
.
ts
import { ElementImageSource } from "pixi.js/html-source";
import type { HTMLSourceCanvas } from "pixi.js/html-source";

const canvas = app.canvas as HTMLSourceCanvas;
const snapshot = canvas.captureElementImage!(element);

const source = new ElementImageSource({ resource: snapshot, autoClose: true });
const sprite = Sprite.from(source);
captureElementImage()
会将元素当前的像素冻结为不可变的
ElementImage
。它没有所属画布,没有
paint
监听器,也没有重绘生命周期,因此源在构造完成后立即就绪。当你需要一个比元素生命周期更长的冻结副本,或者需要进行传输(如过渡效果、“破碎”或拖尾效果)时,可以使用它。使用完成后调用
snapshot.close()
释放快照,或者设置
autoClose: true
让源在
destroy()
时自动关闭它。

Using the source on a sprite, texture, or mesh

在精灵、纹理或网格上使用源

Both sources are normal
TextureSource
s. Wrap them with
Sprite.from(source)
/
Texture.from(source)
, frame or slice them into sub-textures, or map them onto a mesh:
ts
import { Rectangle, Texture } from "pixi.js";

// A 64x64 slice of the rendered element.
const chunk = new Texture({
  source,
  frame: new Rectangle(0, 0, 64, 64),
});

// Mapped onto geometry (e.g. a perspective warp).
const mesh = new PerspectiveMesh({ texture: Texture.from(source) /* ... */ });
两个源都是标准的
TextureSource
。可以用
Sprite.from(source)
/
Texture.from(source)
包装它们,将其裁剪为子纹理,或者映射到网格上:
ts
import { Rectangle, Texture } from "pixi.js";

// 渲染元素的64x64切片。
const chunk = new Texture({
  source,
  frame: new Rectangle(0, 0, 64, 64),
});

// 映射到几何体上(如透视扭曲)。
const mesh = new PerspectiveMesh({ texture: Texture.from(source) /* ... */ });

Auto-detection and priority

自动检测与优先级

ts
// Resolves to an HTMLSource (element) or ElementImageSource (snapshot) only as a last resort.
const sprite = Sprite.from(elementAlreadyInTheCanvas);
A generic HTML element or an
ElementImage
passed to
Texture.from
/
Sprite.from
resolves to these sources at the lowest texture-source priority (
-10
), so they only claim a resource no other built-in source handles. Image, video, and canvas elements are deliberately rejected; they have dedicated, faster sources. Construct the source explicitly when you need options (
autoUpdate
,
autoClose
) or non-HTML elements such as SVG.
ts
// 仅作为最后手段,解析为HTMLSource(元素)或ElementImageSource(快照)。
const sprite = Sprite.from(elementAlreadyInTheCanvas);
传递给
Texture.from
/
Sprite.from
的通用HTML元素或
ElementImage
会以最低的纹理源优先级(
-10
)解析为这些源,因此它们仅会处理其他内置源无法处理的资源。图片、视频和画布元素会被刻意排除;它们有专门的、更快的源。当你需要自定义选项(
autoUpdate
autoClose
)或处理SVG等非HTML元素时,请显式构造源。

Common Mistakes

常见错误

[HIGH] Not importing pixi.js/html-source

[高风险] 未导入pixi.js/html-source

Wrong:
ts
import { HTMLSource } from "pixi.js/html-source";
// ...but never importing the side effect, in a build that tree-shakes it away
Correct:
ts
import "pixi.js/html-source";
import { HTMLSource } from "pixi.js/html-source";
The
'html'
uploaders are registered by the side-effect import. Without it, the source has no uploader and the texture never renders.
错误写法:
ts
import { HTMLSource } from "pixi.js/html-source";
// ...但从未导入副作用模块,且构建时被摇树优化移除
正确写法:
ts
import "pixi.js/html-source";
import { HTMLSource } from "pixi.js/html-source";
'html'
上传器是通过副作用导入注册的。如果不导入它,源将没有上传器,纹理也无法渲染。

[HIGH] Assuming the browser API is enabled

[高风险] 假设浏览器API已启用

The HTML-in-Canvas proposal is not shipped by default. If the API is disabled, the uploader throws on first render. Feature-detect first:
ts
const canvas = app.canvas as HTMLSourceCanvas;
if (!canvas.requestPaint) {
  // Fall back to a static image, DOMContainer overlay, or a message.
}
HTML-in-Canvas提案尚未默认启用。如果API被禁用,上传器会在首次渲染时抛出错误。请先进行特性检测:
ts
const canvas = app.canvas as HTMLSourceCanvas;
if (!canvas.requestPaint) {
  // 回退到静态图片、DOMContainer叠加层或提示信息。
}

[MEDIUM] Element not a direct child of the canvas

[中风险] 元素不是画布的直接子元素

ts
document.body.appendChild(form); // wrong parent
const source = new HTMLSource({ resource: form }); // throws
HTMLSource
requires the element to be a direct child of the owning canvas (
app.canvas.appendChild(form)
) and throws otherwise. Append the element to the canvas before constructing the source, or pass the
canvas
option.
ts
document.body.appendChild(form); // 错误的父元素
const source = new HTMLSource({ resource: form }); // 抛出错误
HTMLSource
要求元素必须是所属画布的直接子元素(
app.canvas.appendChild(form)
),否则会抛出错误。请在构造源之前将元素添加到画布中,或者传入
canvas
选项。

[MEDIUM] Expecting a live element to update without requestPaint

[中风险] 期望实时元素在未调用requestPaint的情况下自动更新

A non-animating element updates automatically on browser
paint
events (
autoUpdate: true
). Content that changes every frame will not re-upload unless something triggers a paint; drive it with
source.requestPaint()
each frame (with
autoRequestPaint: false
).
非动画元素会在浏览器
paint
事件中自动更新(
autoUpdate: true
)。内容每一帧都变化的元素不会自动重新上传,除非有触发绘制的操作;请在每一帧调用
source.requestPaint()
(配合
autoRequestPaint: false
)来驱动更新。

[MEDIUM] Closing an ElementImage still in use

[中风险] 关闭仍在使用的ElementImage

ts
const source = new ElementImageSource({ resource: snapshot, autoClose: true });
const other = new ElementImageSource({ resource: snapshot }); // shares the snapshot

source.destroy(); // closes the snapshot — `other` is now a use-after-free
Only set
autoClose: true
when the source owns the snapshot exclusively. For a shared snapshot, leave
autoClose
off and call
snapshot.close()
once, after the last source is destroyed.
ts
const source = new ElementImageSource({ resource: snapshot, autoClose: true });
const other = new ElementImageSource({ resource: snapshot }); // 共享快照

source.destroy(); // 关闭快照 —— `other`现在会出现使用已释放资源的问题
只有当源独占快照时,才设置
autoClose: true
。对于共享快照,请保持
autoClose
false
,并在最后一个源销毁后调用
snapshot.close()

Cleanup

清理

ts
source.destroy();
HTMLSource.destroy()
detaches the canvas
paint
listener and nulls its canvas reference.
ElementImageSource.destroy()
closes the snapshot when
autoClose
was set; otherwise call
snapshot.close()
yourself to release the memory.
ts
source.destroy();
HTMLSource.destroy()
会移除画布的
paint
监听器并清空其画布引用。当设置了
autoClose
时,
ElementImageSource.destroy()
会关闭快照;否则请自行调用
snapshot.close()
来释放内存。

API Reference

API参考