Signatur
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
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);
});
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'));
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);
});
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'))
);
// Wichtig · Fallstricke
- Verunreinigtes Canvas (tainted canvas): Wurden Bilder von fremden Origins ohne CORS-Freigabe gezeichnet, wirft
toBlob()einenSecurityError. Abhilfe schafftimg.crossOrigin = 'anonymous'zusammen mit passendenAccess-Control-Allow-Origin-Headern auf dem Server. nullim Callback: Ist das Canvas 0 × 0 Pixel groß oder überschreitet es die Größenlimits des Browsers, erhält der Callbacknull. 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 mitURL.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 stattdessenOffscreenCanvas.convertToBlob()zur Verfügung.