Start · Sprachen · JavaScript · Referenz · OffscreenCanvasRenderingContext2D

OffscreenCanvasRenderingContext2D

Schnittstelle

2D-Rendering-Kontext zum Zeichnen auf das Bitmap eines <code>OffscreenCanvas</code>, auch in Web Workers ohne Zugriff auf das DOM nutzbar.

seit JavaScript Baseline 2023: Chrome 69, Firefox 105, Safari 16.4 Kategorie: webapi

Signatur

interface OffscreenCanvasRenderingContext2D

Beschreibung

OffscreenCanvasRenderingContext2D ist das Gegenstück zu CanvasRenderingContext2D für OffscreenCanvas-Objekte. Du erhältst ihn über offscreen.getContext("2d"). Er bietet fast dieselbe Zeichen-API: Pfade (beginPath(), arc(), lineTo()), Rechtecke, Text (fillText(), measureText()), Transformationen, Verläufe, Muster, Bilddaten (getImageData(), putImageData()) und drawImage().

Der größte Vorteil: Der Kontext funktioniert auch in einem Web Worker. Aufwendiges Rendering, etwa Diagramme, Spielgrafik, Bildfilter oder Kachelgenerierung, läuft dann abseits des Hauptthreads, und die Benutzeroberfläche bleibt flüssig. Ein sichtbares <canvas> kannst du mit canvas.transferControlToOffscreen() an einen Worker übergeben. Alternativ renderst du in ein eigenständiges OffscreenCanvas und holst das Ergebnis mit transferToImageBitmap() oder convertToBlob() ab.

Im Unterschied zu CanvasRenderingContext2D gibt es alles nicht, was das DOM braucht. Es fehlen zum Beispiel drawFocusIfNeeded() und scrollPathIntoView(). Die Eigenschaft canvas verweist auf das zugehörige OffscreenCanvas statt auf ein HTMLCanvasElement. Einstellungen wie alpha oder willReadFrequently übergibst du beim Aufruf von getContext().

Parameter

Name Typ Default Beschreibung
$contextType Pflicht "2d" Wird an OffscreenCanvas.prototype.getContext() übergeben. Mit "2d" erhältst du einen OffscreenCanvasRenderingContext2D.
$contextAttributes { alpha?: boolean, willReadFrequently?: boolean, colorSpace?: "srgb" | "display-p3", desynchronized?: boolean } { alpha: true, willReadFrequently: false, colorSpace: "srgb" } Optionale Einstellungen für den Kontext. willReadFrequently: true beschleunigt häufige Aufrufe von getImageData().

Rückgabewert

Typ
OffscreenCanvasRenderingContext2D | null
Beschreibung
Der 2D-Kontext des OffscreenCanvas. Der Rückgabewert ist null, wenn das Canvas bereits einen anderen Kontexttyp (z. B. "webgl") verwendet.

Beispiele

Kontext erzeugen und im Hauptthread zeichnen

const offscreen = new OffscreenCanvas(200, 100);
const ctx = offscreen.getContext('2d');

ctx.fillStyle = '#0a7';
ctx.fillRect(0, 0, 200, 100);
ctx.fillStyle = '#fff';
ctx.font = '20px sans-serif';
ctx.fillText('Hallo Offscreen', 20, 55);

// Ergebnis auf ein sichtbares Canvas übertragen
const visible = document.querySelector('canvas');
const bitmapCtx = visible.getContext('bitmaprenderer');
bitmapCtx.transferFromImageBitmap(offscreen.transferToImageBitmap());

console.log(ctx instanceof OffscreenCanvasRenderingContext2D);
true

Canvas-Steuerung an einen Worker übergeben (Animation)

// main.js
const canvas = document.querySelector('#chart');
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker('render-worker.js');
worker.postMessage({ canvas: offscreen }, [offscreen]);

// render-worker.js
self.onmessage = ({ data }) => {
  const ctx = data.canvas.getContext('2d');
  let angle = 0;
  const draw = () => {
    const { width, height } = ctx.canvas;
    ctx.clearRect(0, 0, width, height);
    ctx.save();
    ctx.translate(width / 2, height / 2);
    ctx.rotate(angle);
    ctx.fillStyle = 'tomato';
    ctx.fillRect(-40, -40, 80, 80);
    ctx.restore();
    angle += 0.02;
    requestAnimationFrame(draw);
  };
  draw();
};

Vorschaubild im Worker erzeugen und als Blob exportieren

// thumb-worker.js
self.onmessage = async ({ data: file }) => {
  const bitmap = await createImageBitmap(file);
  const scale = 150 / Math.max(bitmap.width, bitmap.height);
  const w = Math.round(bitmap.width * scale);
  const h = Math.round(bitmap.height * scale);

  const canvas = new OffscreenCanvas(w, h);
  const ctx = canvas.getContext('2d');
  ctx.imageSmoothingQuality = 'high';
  ctx.drawImage(bitmap, 0, 0, w, h);
  bitmap.close();

  const blob = await canvas.convertToBlob({ type: 'image/webp', quality: 0.8 });
  self.postMessage(blob);
};

Pixel lesen mit willReadFrequently

const canvas = new OffscreenCanvas(4, 4);
const ctx = canvas.getContext('2d', { willReadFrequently: true });
ctx.fillStyle = 'rgb(255, 0, 0)';
ctx.fillRect(0, 0, 4, 4);

const { data } = ctx.getImageData(0, 0, 1, 1);
console.log([...data]);
[255, 0, 0, 255]

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Der 2D-Kontext für OffscreenCanvas gibt es in Chrome/Edge seit Version 69, in Firefox seit 105 und in Safari erst seit 16.4. Ältere Safari-Versionen kennen nur WebGL oder gar nichts. Prüfe daher vorher mit typeof OffscreenCanvas !== 'undefined' und prüfe auch das Ergebnis von getContext('2d').
  • Nach transferControlToOffscreen() kannst du auf dem ursprünglichen <canvas> weder getContext() aufrufen noch width/height ändern. Größenänderungen müssen im Worker über ctx.canvas.width passieren.
  • Schriften: Im Worker stehen Webfonts aus dem CSS des Dokuments nicht automatisch zur Verfügung. Lade sie bei Bedarf mit new FontFace() und self.fonts.add().
  • drawImage() akzeptiert im Worker nur Quellen wie ImageBitmap, OffscreenCanvas, VideoFrame oder ImageData (über putImageData()). DOM-Elemente wie HTMLImageElement gibt es dort nicht.
  • Sicherheit: Wenn du Bilder aus fremden Quellen ohne CORS zeichnest, gilt das Canvas als „tainted“. Dann werfen getImageData() und convertToBlob() einen SecurityError.
  • transferToImageBitmap() leert das Canvas. Die Methoden drawFocusIfNeeded() und scrollPathIntoView() gibt es in diesem Kontext nicht.