Signatur
Beschreibung
transferToImageBitmap() nimmt den aktuellen Inhalt eines OffscreenCanvas und gibt ihn als ImageBitmap zurück. Die Methode arbeitet synchron. Die Bilddaten werden dabei nicht kopiert, sondern übertragen, deshalb ist sie sehr schnell. Das ist der wesentliche Unterschied zu createImageBitmap(), das eine Kopie anlegt und ein Promise zurückgibt.
Nach dem Aufruf bekommt der OffscreenCanvas einen neuen, leeren Zeichenpuffer. Bei 2D-Kontexten ist er transparent schwarz. Bei WebGL-Kontexten wird der Zeichenpuffer entsprechend den Kontextattributen geleert. Man zeichnet also jedes Bild neu und überträgt es danach.
Typischerweise nutzt man die Methode so: In einem Web Worker werden Bilder in einen OffscreenCanvas gerendert, der mit new OffscreenCanvas(w, h) erzeugt wurde. Jedes fertige Bild wird mit transferToImageBitmap() herausgelöst und per postMessage() als übertragbares Objekt an den Haupt-Thread geschickt. Dort zeigt ein <canvas> mit dem Kontext "bitmaprenderer" das Bild über transferFromImageBitmap() ohne Kopie an. So kann ein Worker auch mehrere sichtbare Canvas-Elemente beliefern.
Wurde der OffscreenCanvas dagegen über canvas.transferControlToOffscreen() erzeugt, erscheint sein Inhalt automatisch im zugehörigen <canvas>. Dann braucht man transferToImageBitmap() meist nicht.
Rückgabewert
ImageBitmap mit dem zuletzt gerenderten Bild. Breite und Höhe entsprechen dem OffscreenCanvas.Beispiele
Einzelbild erzeugen und im Haupt-Thread anzeigen
// Offscreen zeichnen
const offscreen = new OffscreenCanvas(200, 100);
const ctx = offscreen.getContext('2d');
ctx.fillStyle = 'steelblue';
ctx.fillRect(0, 0, 200, 100);
ctx.fillStyle = 'white';
ctx.font = '20px sans-serif';
ctx.fillText('Hallo!', 60, 55);
// Bild herauslösen – der Offscreen-Puffer ist danach leer
const bitmap = offscreen.transferToImageBitmap();
console.log(bitmap.width, bitmap.height);
// Ohne Kopie in ein sichtbares Canvas übernehmen
const canvas = document.querySelector('#ausgabe');
const renderer = canvas.getContext('bitmaprenderer');
renderer.transferFromImageBitmap(bitmap);
Worker rendert, Haupt-Thread zeigt an
// worker.js
const offscreen = new OffscreenCanvas(300, 150);
const ctx = offscreen.getContext('2d');
let x = 0;
const render = () => {
ctx.clearRect(0, 0, 300, 150);
ctx.fillStyle = 'tomato';
ctx.fillRect(x, 50, 50, 50);
x = (x + 2) % 300;
const bitmap = offscreen.transferToImageBitmap();
// Als übertragbares Objekt senden (keine Kopie)
self.postMessage({ bitmap }, [bitmap]);
requestAnimationFrame(render); // in Workern: Chrome, Firefox
};
render();
// main.js
const worker = new Worker('worker.js');
const view = document.querySelector('canvas').getContext('bitmaprenderer');
worker.addEventListener('message', ({ data }) => {
view.transferFromImageBitmap(data.bitmap);
});
Puffer wird nach dem Transfer zurückgesetzt
const oc = new OffscreenCanvas(1, 1);
const ctx = oc.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 1, 1);
console.log(ctx.getImageData(0, 0, 1, 1).data); // vorher
const bmp = oc.transferToImageBitmap();
console.log(ctx.getImageData(0, 0, 1, 1).data); // nachher
bmp.close(); // Speicher freigeben
// Wichtig · Fallstricke
- Der Canvas-Inhalt wird geleert: Nach dem Aufruf ist der Zeichenpuffer leer. Wer auf den bisherigen Inhalt aufbauen will, muss ihn neu zeichnen oder stattdessen
createImageBitmap(offscreen)verwenden, das eine Kopie erzeugt. - Die Methode wirft einen
InvalidStateError, wenn der Canvas noch keinen Rendering-Kontext hat (alsogetContext()nie aufgerufen wurde) oder wenn der Kontext"bitmaprenderer"ist. - Speicher: Ein
ImageBitmapbelegt Grafikspeicher. Nicht mehr benötigte Bitmaps sollte man mitbitmap.close()freigeben.transferFromImageBitmap()übernimmt die Bitmap und macht sie danach unbrauchbar. Beim Senden perpostMessagesollte die Bitmap in der Transfer-Liste stehen, sonst wird sie kopiert. - Kompatibilität:
OffscreenCanvasist erst seit Safari 16.4 und Firefox 105 vollständig verfügbar. WebGL im Offscreen-Kontext unterstützt Safari erst ab Version 17. In Workern gibt esrequestAnimationFramenicht überall. Als Ersatz dientsetTimeout.