toBlob – canvas als Bilddatei exportieren
canvas.toBlob erweitert die Techniken zum Umwandeln der Zeichnung im Canvas. Ein Blob kann als URL für ein a-Element oder als src-Attribut eines img-Tags eingesetzt werden und die Daten können dem Benutzer zum Download angeboten werden.
toBlob – Zeichnung im canvas zum Download anbieten
canvas.toBlob hält die Zeichnung auf einem HTML-Canvas-Element fest und bietet sie als PNG, JPG oder WebP zum Download an.
toBlob setzt als Argument eine Callback-Funktion, die den Blob erzeugt. Weitere Argumente sind der Mime-Type (PNG, JPG, WebP), und falls JPG/WebP erzeugt werden soll, die Qualitätsstufe.
canvas.toBlob((blob) => {
// reserviert intern Speicher
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "image.png";
a.click();
// räumt auf
URL.revokeObjectURL(url);
}, "image/png");
URL.revokeObjectURL(url); gibt die zuvor erzeugte BLOB-URL wieder frei, sonst kommt es schnell zu Memory Leaks bei zu vielen Bildern / Downloads.
Per Vorgabe erzeugt toBlob ein PNG.
Der moderne Ansatz: toBlob() statt toDataURL()
- speichereffizient (kein riesiger Base64-String)
- async (blockiert UI nicht)
- unterstützt: "image/png", "image/jpeg", "image/webp"
| Format | Eigenschaften |
|---|---|
| PNG | verlustfrei, größer |
| JPEG | verlustbehaftet, kleiner |
| WebP | modern, oft beste Wahl |
canvas.toBlob funktioniert mit 2D-Canvas und auch mit WebGL-Canvas, aber dann sollte preserveDrawingBuffer: true nicht fehlen, sonst ist das Bild evtl. leer.
const gl = canvas.getContext("webgl", {
preserveDrawingBuffer: true
});
Download SVG als PNG/WebP mit canvas.toBlob
Das ist eine typische Aufgabe für das canvas-Element und canvas.toBlob:
SVG → Image → Canvas → PNG/WebP/JPEG.
Die Transformation funktioniert im Browser, braucht keinen Server, ist flexibel, was Skalierung und Filter betrifft und ist schnell implementiert. Erst wenn viele Bilder transformiert werden sollen, die SVGs komplex sind, wenn z.B. auch die Druckqualität und eine bessere Schriftqualität eine Rolle spielt, werden eher Libraries wie librsvg und ImageMagick eingesetzt.
Upload + Vorschau
upload.addEventListener("change", async (e) => {
const file = e.target.files[0];
if (!file) return;
currentSVGText = await file.text();
// SVG anzeigen
preview.innerHTML = currentSVGText;
});
SVG → Canvas → Download
async function downloadCurrentSVG(format = "png") {
if (!currentSVGText) {
alert("Bitte erst ein SVG hochladen");
return;
}
const svgBlob = new Blob([currentSVGText], { type: "image/svg+xml" });
const blobUrl = URL.createObjectURL(svgBlob);
const img = new Image();
img.src = blobUrl;
await new Promise(resolve => img.onload = resolve);
const inputWidth = Number(document.getElementById("svgwidth").value) || 500;
const { width, height } = getSVGSize(currentSVGText, inputWidth);
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
// wichtig: skalieren!
ctx.drawImage(img, 0, 0, width, height);
const mime = format === "webp" ? "image/webp" : "image/png";
canvas.toBlob(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `converted.${format}`;
a.click();
URL.revokeObjectURL(url);
}, mime);
}
WebP-Qualität steuern
Im Grunde genommen ist es einfach, die Qualität des WebP zu steuern, nur ein paar Details sollten beachtet werden.
canvas.toBlob(callback, "image/webp", quality);
Mit dem Wert 0.8 für die Qualität verspricht toBlob eine gute Qualität bei einer deutlich kleineren Datei. So ab 0.6 können erste Folgen der Komprimierung sichtbar werden, bei 0.3 kommt es zu sichtbaren Artefakten.
canvas.toBlob(blob => {
// use blob
}, "image/webp", 0.8);
oder
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, "image/webp", 0.8)
);
WebP unterstützt auch Transparenz. Dabei Sollte die Qualität eher bei 0.8 bis 0.9 liegen.
canvas.toDataURL – der »alte Klassiker«
Für die Umwandlung der Bitmap des canvas-Elements ist heute canvas.toBlob() die bevorzugte Lösung. Der Klassiker war toDataURL.
Der Unterschied zwischen toBlob und toDataURL(): toDataURL ist synchron und blockiert die Benutzerschnittstelle, während canvas.toBlob die eigentliche Konvertierung in ein Bild asynchron durchführt.
- großer Base64-String (≈ +33% Größe)
- sehr langsam bei großen Bildern
- blockiert den Hauptthread
| Kriterium | canvas.toDataURL() | canvas.toBlob() |
|---|---|---|
| Ausgabeformat | Base64-String (data:image/png;base64,...) | Binäres Blob-Objekt |
| Größe der Daten | Meist größer (wegen Base64-Overhead) | Effizienter (kleiner) |
| Speichern / Upload | Umständlicher (Base64 muss konvertiert werden) | Direkt als Datei/Blob verwendbar |
| Kompatibilität | Breite Unterstützung überall | Ältere Browser (< Edge 18) brauchen Fallback |
| Performance | Langsamer bei großen Bildern | Schneller, asynchron |
| Synchron / Async | Synchron (blockierend!) | Asynchron (besser für große Datenmengen) |