Signatur
Beschreibung
Der Konstruktor OffscreenCanvas() legt eine Zeichenfläche an, die nicht an ein <canvas>-Element im Dokument gebunden ist. Man kann darauf genauso zeichnen wie auf ein normales Canvas: mit getContext("2d"), "webgl", "webgl2", "bitmaprenderer" oder "webgpu". Der Inhalt wird aber nicht direkt angezeigt.
Sein großer Vorteil: Er ist auch in Web Workern verfügbar. Aufwendige Rendering-Arbeit wie Bildbearbeitung, Diagramme, Spiele-Rendering oder das Erzeugen von Vorschaubildern lässt sich damit vom Hauptthread in einen Worker verlagern. Die Benutzeroberfläche bleibt dadurch flüssig.
Das Ergebnis lässt sich auf verschiedene Wege weiterverwenden:
- mit
transferToImageBitmap()alsImageBitmapan ein sichtbares Canvas übergeben, - mit
convertToBlob()als PNG, JPEG oder WebP exportieren, - als Bildquelle für
drawImage()nutzen.
Alternativ kann man mit HTMLCanvasElement.transferControlToOffscreen() ein sichtbares Canvas an einen Worker übergeben. Dieses OffscreenCanvas entsteht dann ohne Konstruktor, und was darauf gezeichnet wird, erscheint automatisch auf der Seite.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $width Pflicht | number | Breite der Zeichenfläche in Pixeln. Der Wert wird in einen vorzeichenlosen Ganzzahlwert (unsigned long long) umgewandelt. Man kann ihn später über die Eigenschaft width ändern. |
|
| $height Pflicht | number | Höhe der Zeichenfläche in Pixeln. Auch dieser Wert wird in eine Ganzzahl umgewandelt und lässt sich über die Eigenschaft height ändern. |
Rückgabewert
OffscreenCanvas-Objekt mit der angegebenen Größe. Es ist anfangs transparent und hat noch keinen Zeichenkontext.Beispiele
Vorschaubild erzeugen und als Blob exportieren
const erzeugeVorschau = async (text) => {
const canvas = new OffscreenCanvas(200, 100);
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#1e88e5';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#fff';
ctx.font = 'bold 24px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text, canvas.width / 2, canvas.height / 2);
// PNG-Blob erzeugen
const blob = await canvas.convertToBlob({ type: 'image/png' });
console.log(blob.type, blob.size > 0);
return URL.createObjectURL(blob);
};
const url = await erzeugeVorschau('Hallo!');
document.querySelector('img').src = url;
Rendering im Web Worker, Anzeige im Hauptthread
// worker.js
self.onmessage = ({ data }) => {
const { width, height } = data;
const canvas = new OffscreenCanvas(width, height);
const ctx = canvas.getContext('2d');
// Aufwendiges Farbverlaufs-Muster berechnen
const img = ctx.createImageData(width, height);
for (let i = 0; i < img.data.length; i += 4) {
const x = (i / 4) % width;
img.data[i] = (x / width) * 255;
img.data[i + 2] = 180;
img.data[i + 3] = 255;
}
ctx.putImageData(img, 0, 0);
const bitmap = canvas.transferToImageBitmap();
self.postMessage(bitmap, [bitmap]); // ImageBitmap übertragen statt kopieren
};
// main.js
const worker = new Worker('worker.js');
const sichtbar = document.querySelector('canvas');
const ctx = sichtbar.getContext('bitmaprenderer');
worker.onmessage = ({ data: bitmap }) => {
ctx.transferFromImageBitmap(bitmap);
};
worker.postMessage({ width: sichtbar.width, height: sichtbar.height });
Feature-Erkennung mit Fallback
const erstelleCanvas = (w, h) => {
if (typeof OffscreenCanvas !== 'undefined') {
return new OffscreenCanvas(w, h);
}
// Fallback für ältere Browser (nur im Hauptthread möglich)
const el = document.createElement('canvas');
el.width = w;
el.height = h;
return el;
};
const canvas = erstelleCanvas(64, 64);
console.log(canvas.constructor.name, canvas.width, canvas.height);
// Wichtig · Fallstricke
- Browser-Unterstützung: Chrome und Edge unterstützen die API seit Version 69, Firefox seit 105. Safari unterstützt den Konstruktor ab 16.4, den 2D-Kontext vollständig aber erst ab Safari 17. Für ältere Browser sollte man mit
typeof OffscreenCanvasprüfen, ob die API vorhanden ist. - Beide Argumente sind Pflicht. Ohne sie wirft der Konstruktor einen
TypeError. Negative Werte oderNaNwerden gemäß WebIDL umgewandelt und können unerwartete Größen ergeben. - Pro Canvas lässt sich nur eine Art von Kontext anlegen. Wer nach
getContext("2d")nochgetContext("webgl")aufruft, bekommtnull. - Wird
widthoderheightgeändert, setzt das den Inhalt und den Zustand des Kontexts zurück, genau wie bei<canvas>. transferToImageBitmap()leert das Canvas. Danach muss man neu zeichnen.- Im Worker gibt es kein DOM. Schriften, die per CSS geladen wurden, stehen dort nicht automatisch zur Verfügung. Man muss sie im Worker über
FontFaceundself.fontsladen. - Sehr große Flächen belegen viel Speicher. Browser haben Obergrenzen für die Canvas-Größe, und bei Überschreitung schlägt das Anlegen des Kontexts oder der Export fehl.
- Bilder von fremden Ursprüngen ohne CORS-Freigabe „verunreinigen“ das Canvas (tainted). Danach werfen
convertToBlob()undgetImageData()einenSecurityError.