Start · Sprachen · JavaScript · Referenz · PaintRenderingContext2D

PaintRenderingContext2D

Schnittstelle

Der 2D-Rendering-Kontext der CSS Painting API, mit dem ein Paint Worklet in seiner <code>paint()</code>-Methode Grafiken für CSS-Eigenschaften wie <code>background-image</code> zeichnet.

seit JavaScript Chromium-Browser (Chrome/Edge 65+, Opera 52+); nic Kategorie: webapi

Signatur

interface PaintRenderingContext2D

Beschreibung

PaintRenderingContext2D ist der Zeichenkontext, den der Browser als erstes Argument an die Methode paint(ctx, size, properties, args) einer Klasse übergibt, die mit registerPaint() in einem Paint Worklet registriert wurde. Das Ergebnis erscheint überall dort, wo in CSS die Funktion paint(name) verwendet wird, etwa in background-image, border-image oder mask-image.

Die Schnittstelle ist eine Teilmenge von CanvasRenderingContext2D. Verfügbar sind unter anderem Zustandsverwaltung (save(), restore()), Transformationen (translate(), rotate(), scale(), setTransform()), Stile und Verläufe (fillStyle, strokeStyle, createLinearGradient(), createRadialGradient(), createPattern()), Rechtecke (fillRect(), clearRect()), Pfade (beginPath(), arc(), lineTo(), bezierCurveTo(), fill(), stroke(), clip()), Linienstile, Schatten, Compositing (globalAlpha, globalCompositeOperation) und drawImage().

Nicht verfügbar sind Textfunktionen (fillText(), measureText(), font), Pixelzugriff (getImageData(), putImageData(), createImageData()) sowie die Eigenschaft canvas. Das verhindert, dass Worklets Pixeldaten auslesen oder Informationen nach außen weitergeben, und erlaubt dem Browser, das Zeichnen außerhalb des Hauptthreads auszuführen.

Man verwendet den Kontext für dekorative, auflösungsunabhängige Effekte, die sich über CSS-Custom-Properties steuern lassen: Muster, Rahmen, Verläufe oder animierbare Hintergründe, ohne zusätzliche DOM-Elemente oder Bilddateien.

Parameter

Name Typ Default Beschreibung
$ctx Pflicht PaintRenderingContext2D Erstes Argument von paint(): der Zeichenkontext. Man erzeugt ihn nicht selbst, der Browser stellt ihn bereit.
$size Pflicht PaintSize Zweites Argument von paint(): Objekt mit width und height der zu bemalenden Fläche in CSS-Pixeln.
$properties Pflicht StylePropertyMapReadOnly Drittes Argument: die über static get inputProperties() angeforderten CSS-Eigenschaften, lesbar mit properties.get('--name').
$args Array<CSSUnparsedValue> [] Viertes Argument: Argumente aus paint(name, …) in CSS, sofern static get inputArguments() definiert ist (nur hinter Flag unterstützt).

Beispiele

Einfaches Schachbrettmuster als Hintergrund

// checkerboard.js – läuft im Paint Worklet
class CheckerboardPainter {
  paint(ctx, size) {
    const tile = 16;
    const colors = ['#e0e0e0', '#9e9e9e'];
    for (let y = 0; y < size.height / tile; y++) {
      for (let x = 0; x < size.width / tile; x++) {
        ctx.fillStyle = colors[(x + y) % 2];
        ctx.fillRect(x * tile, y * tile, tile, tile);
      }
    }
  }
}
registerPaint('checkerboard', CheckerboardPainter);

// main.js – im Hauptdokument
if ('paintWorklet' in CSS) {
  CSS.paintWorklet.addModule('checkerboard.js');
}

/* CSS:
.box { background-image: paint(checkerboard); }
*/

Über Custom Properties steuerbarer Kreis

// dot.js
registerPaint('dot', class {
  static get inputProperties() {
    return ['--dot-color', '--dot-size'];
  }

  paint(ctx, { width, height }, props) {
    const color = props.get('--dot-color').toString().trim() || 'tomato';
    const radius = parseFloat(props.get('--dot-size').toString()) || 20;

    ctx.beginPath();
    ctx.arc(width / 2, height / 2, radius, 0, Math.PI * 2);
    ctx.fillStyle = color;
    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
    ctx.shadowBlur = 8;
    ctx.fill();
  }
});

/* CSS:
.badge {
  --dot-color: steelblue;
  --dot-size: 30;
  background-image: paint(dot);
}
*/

Verlauf mit Transformation und Zustandsverwaltung

// stripes.js
registerPaint('stripes', class {
  paint(ctx, size) {
    const grad = ctx.createLinearGradient(0, 0, size.width, 0);
    grad.addColorStop(0, '#ff6b6b');
    grad.addColorStop(1, '#4ecdc4');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, size.width, size.height);

    ctx.save();
    ctx.globalAlpha = 0.2;
    ctx.fillStyle = '#fff';
    ctx.rotate(-Math.PI / 4);
    for (let i = -size.height; i < size.width + size.height; i += 20) {
      ctx.fillRect(i, -size.height, 8, size.width + size.height * 2);
    }
    ctx.restore();

    // Feature-Test: Text gibt es hier nicht
    console.log(typeof ctx.fillText); // Ausgabe in der Worklet-Konsole
  }
});
undefined

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Die CSS Painting API wird nur von Chromium-basierten Browsern unterstützt (Chrome, Edge, Opera). Firefox und Safari unterstützen sie nicht. Vorher mit 'paintWorklet' in CSS prüfen und in CSS einen Fallback setzen, z. B. zuerst background-image: linear-gradient(…) und danach background-image: paint(name).
  • Eingeschränkter Funktionsumfang: Es gibt kein fillText(), getImageData(), putImageData() und keine Eigenschaft canvas. Code aus Canvas-Projekten lässt sich deshalb nicht immer eins zu eins übernehmen.
  • Kein Zustand zwischen Aufrufen: Der Browser kann paint() jederzeit und in mehreren Worklet-Instanzen aufrufen. Deshalb keine Daten in Instanzfeldern ablegen, von denen die Ausgabe abhängt. Das Zeichnen muss deterministisch sein.
  • Sichere Umgebung: addModule() funktioniert nur in einem sicheren Kontext (HTTPS oder localhost). Im Worklet gibt es weder DOM, fetch noch Timer.
  • Transparenz: Mit registerPaint(name, class, { alpha: false }) bzw. static get contextOptions() { return { alpha: false }; } ist der Kontext undurchsichtig. Das kann schneller sein, macht aber durchscheinende Bereiche unmöglich.
  • Leistung: Bei jeder Größenänderung und jeder Änderung der beobachteten Eigenschaften wird neu gezeichnet. Aufwendige Schleifen daher kurz halten, besonders wenn Custom Properties animiert werden.