Start · Sprachen · JavaScript · Referenz · HTMLCanvasElement.toBlob()

HTMLCanvasElement.toBlob()

Methode

Erzeugt asynchron ein <code>Blob</code>-Objekt mit dem aktuellen Canvas-Inhalt als Bilddatei (z. B. PNG, JPEG oder WebP) und übergibt es an einen Callback.

seit JavaScript Baseline: alle modernen Browser (seit 2019 weit ve Kategorie: webapi

Signatur

HTMLCanvasElement.prototype.toBlob(callback, type, quality)

Beschreibung

toBlob() wandelt den Pixelinhalt eines <canvas>-Elements in eine kodierte Bilddatei um und liefert sie als Blob an eine Callback-Funktion. Anders als toDataURL() arbeitet die Methode asynchron und erzeugt keinen riesigen Base64-String. Das spart Speicher und blockiert den Hauptthread bei großen Bildern weniger.

Typische Einsatzfälle sind das Hochladen bearbeiteter oder verkleinerter Bilder per fetch() und FormData, das Anbieten eines Downloads über URL.createObjectURL(), das Kopieren in die Zwischenablage mit ClipboardItem und das clientseitige Komprimieren von Fotos vor dem Upload.

Standardmäßig wird PNG erzeugt. Mit type und quality legst du Format und Kompressionsgrad fest. Den Parameter quality werten Browser nur bei verlustbehafteten Formaten wie image/jpeg und image/webp aus. Fordert man ein Format an, das der Browser nicht unterstützt, bekommt man stillschweigend PNG zurück. Prüfe darum bei Bedarf blob.type.

Die Methode gibt selbst kein Promise zurück. In modernem Code verpackt man sie deshalb meist in ein Promise, damit man sie mit async/await nutzen kann. In Workern und für OffscreenCanvas gibt es stattdessen OffscreenCanvas.convertToBlob(), das direkt ein Promise liefert.

Parameter

Name Typ Default Beschreibung
$callback Pflicht (blob: Blob | null) => void Funktion, die mit dem fertigen Blob aufgerufen wird. Kann das Bild nicht erzeugt werden (z. B. Canvas mit Breite oder Höhe 0 oder zu groß), erhält sie null.
$type string "image/png" MIME-Typ des gewünschten Bildformats, z. B. "image/jpeg" oder "image/webp". Nicht unterstützte Typen fallen auf "image/png" zurück.
$quality number browserabhängig (meist 0.92 bei JPEG, 0.8 bei WebP) Wert zwischen 0 und 1, der die Bildqualität bei verlustbehafteten Formaten festlegt. Wird bei PNG und bei ungültigen Werten ignoriert.

Rückgabewert

Typ
void
Beschreibung
Kein direkter Rückgabewert (undefined). Das Ergebnis kommt asynchron über den callback.

Beispiele

Canvas als PNG herunterladen

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'tomato';
ctx.fillRect(20, 20, 160, 100);

canvas.toBlob((blob) => {
  if (!blob) {
    console.error('Bild konnte nicht erzeugt werden');
    return;
  }
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = 'zeichnung.png';
  link.click();
  // Speicher wieder freigeben
  setTimeout(() => URL.revokeObjectURL(url), 0);
  console.log(blob.type, blob.size);
});
image/png 1234 (Größe variiert)

Promise-Wrapper mit async/await und JPEG-Upload

const canvasToBlob = (canvas, type = 'image/png', quality) =>
  new Promise((resolve, reject) => {
    canvas.toBlob(
      (blob) => (blob ? resolve(blob) : reject(new Error('toBlob fehlgeschlagen'))),
      type,
      quality
    );
  });

const uploadCanvas = async (canvas) => {
  const blob = await canvasToBlob(canvas, 'image/jpeg', 0.85);
  const formData = new FormData();
  formData.append('bild', blob, 'foto.jpg');
  const response = await fetch('/api/upload', { method: 'POST', body: formData });
  console.log('Upload-Status:', response.status);
};

uploadCanvas(document.querySelector('canvas'));
Upload-Status: 200

Foto vor dem Upload verkleinern und als WebP komprimieren

const input = document.querySelector('input[type=file]');

input.addEventListener('change', async () => {
  const file = input.files[0];
  if (!file) return;

  const bitmap = await createImageBitmap(file);
  const scale = Math.min(1, 1200 / bitmap.width);
  const canvas = document.createElement('canvas');
  canvas.width = Math.round(bitmap.width * scale);
  canvas.height = Math.round(bitmap.height * scale);
  canvas.getContext('2d').drawImage(bitmap, 0, 0, canvas.width, canvas.height);

  canvas.toBlob((blob) => {
    // Fallback erkennen: nicht unterstützte Formate liefern PNG
    console.log(`Format: ${blob.type}, vorher ${file.size} B, nachher ${blob.size} B`);
  }, 'image/webp', 0.8);
});
Format: image/webp, vorher 3481920 B, nachher 214337 B

Canvas-Inhalt in die Zwischenablage kopieren

const copyCanvas = async (canvas) => {
  const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
  await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
  console.log('Bild kopiert');
};

document.querySelector('#copy').addEventListener('click', () =>
  copyCanvas(document.querySelector('canvas'))
);
Bild kopiert

// Wichtig · Fallstricke

  • Verunreinigtes Canvas (tainted canvas): Wurden Bilder von fremden Origins ohne CORS-Freigabe gezeichnet, wirft toBlob() einen SecurityError. Abhilfe schafft img.crossOrigin = 'anonymous' zusammen mit passenden Access-Control-Allow-Origin-Headern auf dem Server.
  • null im Callback: Ist das Canvas 0 × 0 Pixel groß oder überschreitet es die Größenlimits des Browsers, erhält der Callback null. Prüfe das immer, bevor du weiterarbeitest.
  • Format-Fallback: Wird ein Format nicht unterstützt (z. B. WebP in älteren Safari-Versionen vor 14), liefert der Browser ohne Warnung PNG. Prüfe deshalb blob.type.
  • Transparenz: JPEG hat keinen Alphakanal. Transparente Bereiche werden meist schwarz. Fülle vorher einen Hintergrund, z. B. mit ctx.fillStyle = '#fff'; ctx.fillRect(...).
  • Speicher: Object-URLs aus URL.createObjectURL() gibst du mit URL.revokeObjectURL() wieder frei.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Ältere Edge- und IE-Versionen boten nur das nicht standardisierte msToBlob(). In Workern steht stattdessen OffscreenCanvas.convertToBlob() zur Verfügung.