Signatur
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
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);
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]);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Der 2D-Kontext für
OffscreenCanvasgibt 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 mittypeof OffscreenCanvas !== 'undefined'und prüfe auch das Ergebnis vongetContext('2d'). - Nach
transferControlToOffscreen()kannst du auf dem ursprünglichen<canvas>wedergetContext()aufrufen nochwidth/heightändern. Größenänderungen müssen im Worker überctx.canvas.widthpassieren. - Schriften: Im Worker stehen Webfonts aus dem CSS des Dokuments nicht automatisch zur Verfügung. Lade sie bei Bedarf mit
new FontFace()undself.fonts.add(). drawImage()akzeptiert im Worker nur Quellen wieImageBitmap,OffscreenCanvas,VideoFrameoderImageData(überputImageData()). DOM-Elemente wieHTMLImageElementgibt es dort nicht.- Sicherheit: Wenn du Bilder aus fremden Quellen ohne CORS zeichnest, gilt das Canvas als „tainted“. Dann werfen
getImageData()undconvertToBlob()einenSecurityError. transferToImageBitmap()leert das Canvas. Die MethodendrawFocusIfNeeded()undscrollPathIntoView()gibt es in diesem Kontext nicht.