Signatur
Beschreibung
PaintWorkletGlobalScope ist der globale Gültigkeitsbereich (globalThis) eines Skripts, das mit CSS.paintWorklet.addModule() geladen wird. Es gehört zur CSS Painting API (Teil von „CSS Houdini“). Damit kannst du Hintergründe, Rahmen oder Masken per JavaScript zeichnen und sie in CSS über die Funktion paint(name) einsetzen, zum Beispiel bei background-image, border-image oder mask-image.
Die zentrale Methode ist registerPaint(name, klasse). Die übergebene Klasse braucht eine Methode paint(ctx, size, properties, args). Der Browser ruft sie immer dann auf, wenn das Element neu gezeichnet werden muss. Mit optionalen statischen Gettern legst du fest, worauf die Klasse reagiert: inputProperties nennt die CSS-Eigenschaften (auch Custom Properties), bei deren Änderung neu gezeichnet wird. inputArguments beschreibt die Argumente der CSS-Funktion paint(), und contextOptions (z. B. { alpha: false }) steuert den Zeichenkontext. Zusätzlich gibt es die Eigenschaft devicePixelRatio. Sie liefert das Verhältnis von physischen zu CSS-Pixeln.
Der Scope ist stark eingeschränkt: Es gibt kein window, kein document, keinen DOM-Zugriff, kein fetch(), keine Timer und keinen Netzwerkzugriff. Der Kontext PaintRenderingContext2D ist eine Teilmenge von CanvasRenderingContext2D ohne Textausgabe und ohne Pixelzugriff wie getImageData(). Der Browser kann mehrere Instanzen des Worklets anlegen und jederzeit verwerfen. Deshalb darf paint() keinen Zustand über Aufrufe hinweg voraussetzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Parameter von registerPaint(): Name des Painters, den du in CSS über paint(name) ansprichst. Er muss eindeutig sein. Ist er leer oder schon vergeben, wird eine Ausnahme geworfen. |
|
| $paintCtor Pflicht | class (Konstruktor) | Parameter von registerPaint(): Klasse mit einer Methode paint(ctx, size, properties, args) und optional den statischen Gettern inputProperties, inputArguments und contextOptions. |
Beispiele
Einfachen Painter registrieren und in CSS nutzen
// checkerboard.js – läuft im PaintWorkletGlobalScope
registerPaint('checkerboard', class {
paint(ctx, size) {
const tile = 16;
for (let y = 0; y < size.height / tile; y++) {
for (let x = 0; x < size.width / tile; x++) {
ctx.fillStyle = (x + y) % 2 ? '#ddd' : '#fff';
ctx.fillRect(x * tile, y * tile, tile, tile);
}
}
}
});
// main.js – im Hauptthread
if ('paintWorklet' in CSS) {
await CSS.paintWorklet.addModule('checkerboard.js');
}
/* CSS:
.box { background-image: paint(checkerboard); }
*/
Auf Custom Properties reagieren (inputProperties)
// ring.js
registerPaint('ring', class {
static get inputProperties() {
return ['--ring-color', '--ring-width'];
}
paint(ctx, size, props) {
const color = props.get('--ring-color').toString().trim() || 'tomato';
const width = parseFloat(props.get('--ring-width').toString()) || 4;
const r = Math.min(size.width, size.height) / 2 - width;
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.arc(size.width / 2, size.height / 2, r, 0, Math.PI * 2);
ctx.stroke();
}
});
/* CSS:
.avatar {
--ring-color: rebeccapurple;
--ring-width: 6;
background-image: paint(ring);
}
.avatar:hover { --ring-color: gold; } // löst ein Neuzeichnen aus
*/
devicePixelRatio und contextOptions verwenden
// lines.js
registerPaint('hairlines', class {
static get contextOptions() {
return { alpha: false }; // undurchsichtiger Hintergrund, schnelleres Zeichnen
}
paint(ctx, size) {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, size.width, size.height);
// Linie mit genau einem physischen Pixel Breite
ctx.lineWidth = 1 / devicePixelRatio;
ctx.strokeStyle = '#999';
for (let y = 0; y < size.height; y += 10) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(size.width, y);
ctx.stroke();
}
}
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Nur Chromium-Browser (Chrome, Edge, Opera) unterstützen die API. Firefox und Safari haben sie nicht umgesetzt. Prüfe daher mit
'paintWorklet' in CSSund lege in CSS einen Ersatz fest, z. B. zuerstbackground: #eee;und danachbackground: paint(x);. - Die API steht nur in einem sicheren Kontext (HTTPS oder localhost) zur Verfügung.
- Es gibt keinen Zugriff auf DOM,
fetch,setTimeoutoder Speicher-APIs. Daten gibst du ausschließlich über CSS-Eigenschaften oder Argumente vonpaint()hinein. - Speichere keinen Zustand in der Klasseninstanz. Der Browser kann jederzeit neue Instanzen erzeugen, und die Reihenfolge der Aufrufe ist nicht garantiert.
PaintRenderingContext2Dkann keinen Text zeichnen (fillTextfehlt) und hat keingetImageData().- Rufst du
registerPaint()zweimal mit demselben Namen auf, wird einInvalidModificationErrorausgelöst. - Eine aufwendige
paint()-Methode wird bei jeder Änderung einer Eingabe-Eigenschaft erneut ausgeführt, etwa bei Animationen. Halte sie deshalb schlank.