Start · Sprachen · JavaScript · Referenz · PaintWorkletGlobalScope

PaintWorkletGlobalScope

Schnittstelle

Das globale Objekt in einem Paint Worklet der CSS Painting API. Über <code>registerPaint()</code> meldet es eigene Zeichenklassen für <code>paint()</code> in CSS an.

seit JavaScript Chromium 65+ (Chrome, Edge, Opera); nicht in Firef Kategorie: webapi

Signatur

interface PaintWorkletGlobalScope extends WorkletGlobalScope

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 CSS und lege in CSS einen Ersatz fest, z. B. zuerst background: #eee; und danach background: paint(x);.
  • Die API steht nur in einem sicheren Kontext (HTTPS oder localhost) zur Verfügung.
  • Es gibt keinen Zugriff auf DOM, fetch, setTimeout oder Speicher-APIs. Daten gibst du ausschließlich über CSS-Eigenschaften oder Argumente von paint() hinein.
  • Speichere keinen Zustand in der Klasseninstanz. Der Browser kann jederzeit neue Instanzen erzeugen, und die Reihenfolge der Aufrufe ist nicht garantiert.
  • PaintRenderingContext2D kann keinen Text zeichnen (fillText fehlt) und hat kein getImageData().
  • Rufst du registerPaint() zweimal mit demselben Namen auf, wird ein InvalidModificationError ausgelöst.
  • Eine aufwendige paint()-Methode wird bei jeder Änderung einer Eingabe-Eigenschaft erneut ausgeführt, etwa bei Animationen. Halte sie deshalb schlank.