HTMLSource et ElementImageSource transforment un élément DOM en TextureSource que vous pouvez utiliser partout où fonctionne une texture normale : sur un Sprite, comme frame de Texture, ou projetée sur un Mesh. HTMLSource reflète les pixels en direct d'un élément dans le GPU (l'élément reste modifiable et cliquable dans le navigateur) ; ElementImageSource encapsule un snapshot immuable qui ne se repeint jamais. Les deux nécessitent un side-effect import 'pixi.js/html-source' pour enregistrer leurs extensions.
Ces sources s'appuient sur la proposition expérimentale HTML-in-Canvas du navigateur et sont marquées EXPERIMENTAL dans PixiJS v8. L'API du navigateur doit être activée sinon l'uploader de texture lance une exception au premier rendu ; faites une détection de fonctionnalité avec
canvas.requestPaintavant de vous en servir. L'API peut changer entre les versions mineures.
Suppose une connaissance de pixijs-scene-sprite et des textures. Ce sont des sources de texture, pas des objets d'affichage : enveloppez-les dans un Sprite (ou Texture/Mesh) pour les placer à l'écran. Non disponible dans les Web Workers ; un worker n'a pas de DOM à capturer.
Démarrage rapide
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);
// L'élément doit être un enfant direct du canvas Pixi.
const form = document.createElement("form");
form.innerHTML = '<input value="still editable" />';
app.canvas.appendChild(form);
// Rendez le formulaire en direct en tant que sprite. Il reste interactif dans le navigateur.
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);
Skills liés : pixijs-scene-sprite (afficher la texture), pixijs-scene-mesh (projeter sur la géométrie, PerspectiveMesh), pixijs-scene-dom-container (l'inverse : superposer du HTML au-dessus du canvas, en dehors du pipeline GPU), pixijs-assets (sources de texture vs le loader/cache), pixijs-environments (pas de DOM dans les Web Workers).
Options du constructeur
Les deux sources étendent TextureSource, donc toutes les TextureSourceOptions (resolution, scaleMode, addressMode, label, etc.) sont valides. resource est requis sur chacune.
HTMLSourceOptions (élément en direct) :
| Option | Type | Par défaut | Description |
|---|---|---|---|
resource |
Element |
— | Requis. L'élément DOM en direct à rendre. Doit être un enfant direct du canvas propriétaire, sinon le constructeur lance une exception. |
canvas |
HTMLSourceCanvas |
— | Le canvas qui possède le sous-arbre de mise en page de l'élément. Déduit de resource.parentElement quand l'élément est un enfant direct du canvas ; passez-le quand l'inférence n'est pas possible. |
autoLayout |
boolean |
true |
Définit l'attribut layoutsubtree sur le canvas propriétaire. Le navigateur ne place en page et ne peint les enfants du canvas que s'il est présent. Mettez false si vous écrivez <canvas layoutsubtree> vous-même. |
autoUpdate |
boolean |
true |
Écoutez l'événement paint du canvas et re-uploadez quand l'élément se repeint. Mettez false pour une texture statique, capturée une seule fois. |
autoRequestPaint |
boolean |
true |
Demandez un repaint initial après la construction. Mettez false et appelez source.requestPaint() vous-même chaque frame pour l'animation continue. |
ElementImageSourceOptions (snapshot immuable) :
| Option | Type | Par défaut | Description |
|---|---|---|---|
resource |
ElementImage |
— | Requis. Un snapshot de canvas.captureElementImage(element). |
autoClose |
boolean |
false |
Appelez snapshot.close() quand la source est détruite. Laissez false quand le snapshot est partagé avec d'autres sources, sinon vous risquez un use-after-free. |
Motifs fondamentaux
Configuration et le side-effect import
import "pixi.js/html-source";
import { HTMLSource, ElementImageSource } from "pixi.js/html-source";
pixi.js/html-source appelle extensions.add(...) pour enregistrer HTMLSource, ElementImageSource, et leurs uploaders WebGL/WebGPU. Sans cela, le renderer n'a pas d'uploader 'html' et ces sources ne se rendent jamais. Les classes sont exportées de pixi.js/html-source, pas de pixi.js.
Importer une export nommée de pixi.js/html-source déclenche aussi le side effect, donc un simple import 'pixi.js/html-source' n'est nécessaire que quand vous n'importez rien d'autre de ce chemin.
Détection de fonctionnalité et support navigateur
L'API HTML-in-Canvas est fermée par un flag du navigateur. Faites une détection de fonctionnalité avant de vous y fier :
import type { HTMLSourceCanvas } from "pixi.js/html-source";
const canvas = app.canvas as HTMLSourceCanvas;
if (canvas.requestPaint) {
// HTML-in-Canvas est disponible.
}
Castez app.canvas en HTMLSourceCanvas pour les membres typés requestPaint et captureElementImage. source.requestPaint() retourne false quand le navigateur n'a pas l'API ; l'uploader de texture lance une exception au premier rendu quand elle est désactivée.
Élément en direct avec HTMLSource
const form = document.createElement("form");
app.canvas.appendChild(form); // enfant direct du canvas
const source = new HTMLSource({ resource: form });
const sprite = Sprite.from(source);
L'élément doit être un enfant direct du <canvas> du renderer ; la source déduit le canvas propriétaire de resource.parentElement (ou passez canvas). Avec les valeurs par défaut, elle définit layoutsubtree sur le canvas, écoute l'événement paint du canvas, et demande un repaint initial. source.isReady est false jusqu'à ce que ce premier repaint arrive, puis true. resourceWidth/resourceHeight rapportent la taille réelle en pixels de l'élément (offsetWidth/offsetHeight).
Animation continue avec requestPaint
const source = new HTMLSource({ resource: clock, autoRequestPaint: false });
const sprite = Sprite.from(source);
app.ticker.add(() => {
clock.textContent = new Date().toLocaleTimeString();
source.requestPaint(); // re-capture le DOM cette frame
});
Le navigateur ne repeint les enfants du canvas que sur demande. Pour un élément dont le contenu change chaque frame, mettez autoRequestPaint: false et appelez source.requestPaint() dans votre propre ticker pour piloter les repaints selon votre calendrier.
Snapshot immuable avec ElementImageSource
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() gèle les pixels actuels d'un élément dans un ElementImage immuable. Il n'y a pas de canvas propriétaire, pas d'écouteur paint, et pas de cycle de vie de repaint, donc la source est prête au moment où elle est construite. Utilisez-la quand vous avez besoin d'une copie gelée qui survit à son élément ou est transférée (transitions, effets de « shatter » ou de traînée). Libérez le snapshot avec snapshot.close() quand vous en avez fini, ou passez autoClose: true pour laisser la source le fermer sur destroy().
Utiliser la source sur un sprite, une texture ou un mesh
Les deux sources sont des TextureSource normales. Enveloppez-les avec Sprite.from(source) / Texture.from(source), découpez-les en sous-textures, ou projetez-les sur un mesh :
import { Rectangle, Texture } from "pixi.js";
// Un slice 64x64 de l'élément rendu.
const chunk = new Texture({
source,
frame: new Rectangle(0, 0, 64, 64),
});
// Projeté sur la géométrie (par ex. une déformation en perspective).
const mesh = new PerspectiveMesh({ texture: Texture.from(source) /* ... */ });
Détection automatique et priorité
// Résout vers HTMLSource (élément) ou ElementImageSource (snapshot) en dernier recours seulement.
const sprite = Sprite.from(elementAlreadyInTheCanvas);
Un élément HTML générique ou un ElementImage passé à Texture.from/Sprite.from résout vers ces sources à la plus basse priorité de source de texture (-10), donc elles ne revendiquent une ressource que si aucune autre source intégrée ne la traite. Les éléments image, vidéo et canvas sont délibérément rejetés ; ils ont des sources dédiées, plus rapides. Construisez la source explicitement quand vous avez besoin d'options (autoUpdate, autoClose) ou d'éléments non-HTML comme SVG.
Erreurs courantes
[ÉLEVÉE] Ne pas importer pixi.js/html-source
Incorrect :
import { HTMLSource } from "pixi.js/html-source";
// ...mais ne jamais importer le side effect, dans un build qui l'élague
Correct :
import "pixi.js/html-source";
import { HTMLSource } from "pixi.js/html-source";
Les uploaders 'html' sont enregistrés par le side-effect import. Sans cela, la source n'a pas d'uploader et la texture ne se rend jamais.
[ÉLEVÉE] Supposer que l'API du navigateur est activée
La proposition HTML-in-Canvas n'est pas livrée par défaut. Si l'API est désactivée, l'uploader lance une exception au premier rendu. Faites d'abord une détection de fonctionnalité :
const canvas = app.canvas as HTMLSourceCanvas;
if (!canvas.requestPaint) {
// Revenez à une image statique, un overlay DOMContainer, ou un message.
}
[MOYENNE] Élément pas enfant direct du canvas
document.body.appendChild(form); // mauvais parent
const source = new HTMLSource({ resource: form }); // lance une exception
HTMLSource nécessite que l'élément soit un enfant direct du canvas propriétaire (app.canvas.appendChild(form)) et lance une exception sinon. Ajoutez l'élément au canvas avant de construire la source, ou passez l'option canvas.
[MOYENNE] S'attendre à ce qu'un élément en direct se mette à jour sans requestPaint
Un élément non-animé se met à jour automatiquement sur les événements paint du navigateur (autoUpdate: true). Le contenu qui change chaque frame ne se re-uploadera pas sauf si quelque chose déclenche un repaint ; pilotez-le avec source.requestPaint() chaque frame (avec autoRequestPaint: false).
[MOYENNE] Fermer un ElementImage encore en usage
const source = new ElementImageSource({ resource: snapshot, autoClose: true });
const other = new ElementImageSource({ resource: snapshot }); // partage le snapshot
source.destroy(); // ferme le snapshot — `other` est maintenant un use-after-free
Mettez autoClose: true uniquement quand la source possède le snapshot exclusivement. Pour un snapshot partagé, laissez autoClose désactivé et appelez snapshot.close() une fois, après la destruction de la dernière source.
Nettoyage
source.destroy();
HTMLSource.destroy() détache l'écouteur paint du canvas et annule sa référence au canvas. ElementImageSource.destroy() ferme le snapshot quand autoClose était défini ; sinon appelez snapshot.close() vous-même pour libérer la mémoire.