Start · Sprachen · JavaScript · Referenz · new OffscreenCanvas()

new OffscreenCanvas()

Methode

Erzeugt ein neues <code>OffscreenCanvas</code>, also eine vom DOM losgelöste Zeichenfläche mit der angegebenen Breite und Höhe in Pixeln. Sie funktioniert auch in Web Workern.

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

Signatur

new OffscreenCanvas(width, height)

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() als ImageBitmap an 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

Typ
OffscreenCanvas
Beschreibung
Ein neues 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;
image/png true

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);
OffscreenCanvas 64 64

// 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 OffscreenCanvas prüfen, ob die API vorhanden ist.
  • Beide Argumente sind Pflicht. Ohne sie wirft der Konstruktor einen TypeError. Negative Werte oder NaN werden 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") noch getContext("webgl") aufruft, bekommt null.
  • Wird width oder height geä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 FontFace und self.fonts laden.
  • 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() und getImageData() einen SecurityError.