> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# SVG auf Canvas: Grafik vor dem PNG-Export laden

> Lade ein vollständiges SVG mit Image.decode, zeichne es in gewählter Bitmapgröße, prüfe CORS und PNG-Auslesung und halte die bearbeitbare Quelle von exportierten Pixeln getrennt.

Source: https://perfectvector.com/de/blog/svg-canvas-image-export

Language: de
Author: Irene Kim
Published: 2026-10-06T08:00:00+09:00
Updated: 2026-10-06T08:00:00+09:00

Um ein vollständiges SVG auf Canvas zu zeichnen, lade es als Bild, warte auf `image.decode()` und übergib dieses Bild an `drawImage()`. Prüfe anschließend den PNG-Export separat. Ein Bild kann auf Canvas erscheinen, während der Browser das Lesen oder Speichern seiner Pixel blockiert.

Dieser Weg zeichnet das SVG-Dokument als Bild. Er gibt dem Canvas keine bearbeitbaren SVG-Pfade. Möchtest du stattdessen ausgewählte Konturen rekonstruieren, verwende den [Path2D-SVG-Leitfaden](https://perfectvector.com/de/blog/canvas-path2d-svg). Behalte das ursprüngliche SVG unabhängig vom gewählten Darstellungsweg.

## Trenne Dekodierung, Zeichnen und Export

Ein `HTMLImageElement` ist eine akzeptierte Eingabe für [Canvas-drawImage()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage). Seine Zielbreite und -höhe steuern die gezeichnete Größe. [Image.decode()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode) gibt ein Promise zurück, das nach dem Dekodieren aufgelöst wird. Ein fehlgeschlagener Abruf oder ein Dekodierungsproblem kann es zurückweisen.

Erfolgreiches Dekodieren ist nur die erste Prüfung. Ein Bild einer anderen Herkunft, das ohne CORS-Erlaubnis geladen wurde, kann weiterhin gezeichnet werden, verunreinigt aber das Canvas. Pixelauslesung und Export scheitern dann. MDNs [Leitfaden zu CORS-freigegebenen Bildern](https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/CORS_enabled_image) erklärt diesen Unterschied.

**Quelle behalten, Pixel prüfen**

![Schematische Illustration einer hohlen Raute und eines Kreises als Quellkonturen, glatt gerenderte Grafik und Pixelraster-Ausgabe](https://perfectvector.com/blog/svg-canvas-image-export/image-and-png.webp)

*Illustration: Quellkonturen und gezeichnete Pixel sind verschiedene Repräsentationen. Rahmen, Pfeile und grobe Raster sind schematisch. Die folgenden Browserergebnisse stammen aus einer unabhängig ausgeführten selbst erstellten Testdatei.*

## Erstelle ein eigenständiges SVG

Speichere dies als `master.svg`. Es enthält einen Pfad und einen Kreis, ohne eingebettetes Bild, Schrift oder externe Abhängigkeit. Die innere Raute und die umgebende Zeichenfläche sind in der Quelle transparent.

```svg
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="160" viewBox="0 0 240 160">
  <path d="M96 24 L152 80 L96 136 L40 80 Z M96 58 L118 80 L96 102 L74 80 Z" fill="#176b5b" fill-rule="evenodd"/>
  <circle cx="200" cy="80" r="24" fill="#d4a53a"/>
</svg>
```

Wir verwenden die vollständige Datei als Bild, einschließlich beider Formen und ihrer `viewBox`. Anders als beim Extrahieren nur des `d`-Werts eines Pfads bitten wir den SVG-Bildrenderer des Browsers, das Dokument zu zeichnen.

Das Beispiel ist bewusst eigenständig. Für SVG als Bild gelten Einschränkungen, unter anderem für externe Ressourcen und Skripte. Siehe [MDNs Leitfaden zu SVG als Bild](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image). Betrachte das erfolgreiche Dekodieren dieser kleinen Datei nicht als Beleg dafür, dass ein beliebiges SVG externe Schriften, Stile oder verknüpfte Grafiken lädt. Vergleiche für die Ausgabe [Inline-SVG und Bildelemente](https://perfectvector.com/de/blog/inline-svg-vs-img).

## Betreibe zwei lokale Herkünfte mit unterschiedlichen CORS-Antworten

Zu einer Herkunft gehört der Port. Der folgende rein lokale Server stellt dieselben SVG-Bytes über zwei Herkünfte bereit. An der zweiten Herkunft enthält `/cors/master.svg` den Header `Access-Control-Allow-Origin: *`; `/plain/master.svg` nicht. Das isoliert die Antwortberechtigung von der Grafik.

Speichere dies als `serve-proof.py` neben dem SVG und dem folgenden HTML. Führe `python3 serve-proof.py` aus und öffne dann `http://127.0.0.1:8770/starter.html`. Beide Ports müssen frei sein. Änderst du sie, aktualisiere Server und HTML gemeinsam. Drücke im Terminal die Eingabetaste, um beide Server zu stoppen.

```python
from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
from threading import Thread

root = Path(__file__).parent
class Handler(SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=str(root), **kwargs)
    def do_GET(self):
        if self.path in ['/cors/master.svg', '/plain/master.svg']:
            payload = (root / 'master.svg').read_bytes()
            self.send_response(200)
            self.send_header('Content-Type', 'image/svg+xml')
            self.send_header('Cache-Control', 'no-store')
            if self.path.startswith('/cors/'):
                self.send_header('Access-Control-Allow-Origin', '*')
            self.end_headers()
            self.wfile.write(payload)
        else:
            super().do_GET()

servers = [ThreadingHTTPServer(('127.0.0.1', port), Handler) for port in (8770, 8783)]
for server in servers:
    Thread(target=server.serve_forever, daemon=True).start()
try:
    input('Original SVG proof on 127.0.0.1:8770 and :8783. Enter to stop.\n')
finally:
    for server in servers:
        server.shutdown()
        server.server_close()
```

Dieser freizügige Header gehört zu einer lokalen Testumgebung, die unsere eigene Grafik bereitstellt. Konfiguriere für einen produktiven Bildhost die passende erlaubte Herkunft auf einem von dir kontrollierten Server. Ein Bildattribut zu setzen gewährt keinen Zugriff auf Inhalte eines anderen Servers.

## Dekodiere das Bild vor dem Zeichnen

Speichere diese vollständige Seite als `starter.html`. Jeder Fall bekommt ein eigenes Canvas. Der verunreinigte Fall kann deshalb die erfolgreichen Fälle nicht beeinträchtigen. Setze bei CORS-Anfragen `crossOrigin` vor `src`, wie [MDNs crossOrigin-Referenz](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/crossOrigin) beschreibt.

Die Canvas-Bitmap ist ausdrücklich `480 × 320` groß; ihre CSS-Darstellungsgröße beträgt `240 × 160`. Die intrinsischen Abmessungen des ursprünglichen Bilds sind `240 × 160`. `drawImage()` skaliert es auf die gewählten Bitmapabmessungen. Das sind gewählte Abmessungen, keine Messung des Geräte-Pixelverhältnisses.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Original SVG to canvas export</title>
<style>
  body { margin: 24px; font: 16px system-ui; background: #f6f2e8; }
  main { display: grid; grid-template-columns: repeat(2, 280px); gap: 20px; }
  figure { margin: 0; }
  canvas { display: block; width: 240px; height: 160px; background: white; }
  figcaption { margin: 6px 0; }
  pre { white-space: pre-wrap; font-size: 12px; }
</style>
<h1>Decode, paint, then check PNG access</h1>
<main id="cases"></main>
<pre id="report"></pre>
<script>
  function pngBlob(canvas) {
    return new Promise((resolve, reject) => {
      try { canvas.toBlob(blob => blob ? resolve(blob) : reject(new Error('Empty PNG')), 'image/png'); }
      catch (error) { reject(error); }
    });
  }
  function dataURL(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject(reader.error);
      reader.readAsDataURL(blob);
    });
  }
  async function render(test) {
    const figure = document.createElement('figure');
    const canvas = document.createElement('canvas');
    canvas.width = 480;
    canvas.height = 320;
    const caption = document.createElement('figcaption');
    figure.append(canvas, caption);
    document.getElementById('cases').append(figure);
    const result = { id: test.id, url: new URL(test.src, location.href).href,
      crossOrigin: test.crossOrigin ?? null, canvasWidth: canvas.width, canvasHeight: canvas.height };
    const image = new Image();
    if (test.crossOrigin) image.crossOrigin = test.crossOrigin;
    image.src = result.url;
    try { await image.decode(); }
    catch (error) {
      result.stage = 'decode';
      result.error = error.name;
      caption.textContent = test.id + ': decode ' + error.name;
      return result;
    }
    result.naturalWidth = image.naturalWidth;
    result.naturalHeight = image.naturalHeight;
    const context = canvas.getContext('2d');
    context.drawImage(image, 0, 0, canvas.width, canvas.height);
    result.stage = 'painted';
    try {
      result.opening = [...context.getImageData(192, 160, 1, 1).data];
      result.fill = [...context.getImageData(192, 80, 1, 1).data];
      result.corner = [...context.getImageData(0, 0, 1, 1).data];
    } catch (error) { result.readbackError = error.name; }
    try {
      const blob = await pngBlob(canvas);
      result.pngType = blob.type;
      result.pngBytes = blob.size;
      result.pngDataURL = await dataURL(blob);
      result.export = 'ok';
      const download = document.createElement('a');
      download.href = result.pngDataURL;
      download.download = test.id + '.png';
      download.textContent = 'Save PNG';
      figure.append(download);
    } catch (error) { result.export = 'failed'; result.exportError = error.name; }
    caption.textContent = test.id + ': ' + result.stage + ', PNG ' + result.export;
    return result;
  }
  async function run() {
    const tests = [
      { id: 'same-origin', src: 'master.svg' },
      { id: 'cors-allowed', src: 'http://127.0.0.1:8783/cors/master.svg', crossOrigin: 'anonymous' },
      { id: 'no-cors-image', src: 'http://127.0.0.1:8783/plain/master.svg' },
      { id: 'cors-denied', src: 'http://127.0.0.1:8783/plain/master.svg', crossOrigin: 'anonymous' },
      { id: 'missing-file', src: 'missing.svg' },
    ];
    const results = [];
    for (const test of tests) results.push(await render(test));
    document.getElementById('report').textContent = JSON.stringify({ pageOrigin: location.origin, results }, (key, value) => key === 'pngDataURL' ? undefined : value, 2);
  }
  run();
</script>
</html>
```

Die Exportfunktion behandelt sowohl eine geworfene Ausnahme als auch ein null-Blob-Ergebnis. [Canvas.toBlob()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) unterstützt PNG-Ausgabe und kann `SecurityError` werfen, wenn das Canvas nicht herkunftsrein ist. Die beiden erfolgreichen Fälle ergänzen einen Link zum Speichern des PNGs. Der sichtbare Bericht lässt die Base64-Nutzlast weg.

## Lies die Fehlerstufe, bevor du das SVG änderst

Wir führten genau diese Vorlage in einer Chrome-Browserumgebung aus und öffneten anschließend beide gespeicherten PNGs erneut. Diese Beobachtungen betreffen die ursprüngliche eigenständige Datei und diese beiden lokalen Herkünfte.

| Fall                                  | Bildanfrage                       | Beobachtetes Zeichnen/Auslesen/Exportieren                            |
| ------------------------------------- | --------------------------------- | --------------------------------------------------------------------- |
| Gleiche Herkunft                      | Lokales SVG, kein CORS-Attribut   | Mit 240 × 160 dekodiert; gezeichnet; Auslesung und PNG erfolgreich    |
| Andere Herkunft, Erlaubnis vorhanden  | `anonymous` plus Antwortheader    | Dekodiert; gezeichnet; Auslesung und PNG erfolgreich                  |
| Andere Herkunft, keine CORS-Anfrage   | Kein Attribut, kein Antwortheader | Dekodiert und gezeichnet; Auslesung und Export warfen `SecurityError` |
| Andere Herkunft, Erlaubnis verweigert | `anonymous`, kein Antwortheader   | Dekodierung mit `EncodingError` zurückgewiesen; kein Zeichenversuch   |
| Fehlende Datei                        | 404 derselben Herkunft            | Dekodierung mit `EncodingError` zurückgewiesen; kein Zeichenversuch   |

Der Fall ohne CORS zeigte die Grafik sichtbar an. Dieses Aussehen belegte keine Erlaubnis zum Lesen oder Exportieren. Der Fall mit verweigertem CORS und die fehlende Datei scheiterten früher. Eine neue Geometrie würde daher keinen dieser Anfragefehler beheben.

Beide exportierten PNGs ließen sich mit `480 × 320` erneut öffnen. In diesem Lauf waren sie byteidentisch und jeweils 10509 Bytes groß. An der Bitmapkoordinate `(192,160)` war die Öffnung `RGBA (0,0,0,0)`. Auch die Ecke hatte Alpha null. Die blaugrüne Probe bei `(192,80)` war `(23,107,91,255)`. Diese Proben prüfen Öffnung und Füllung dieser Datei, nicht jeden Kantenpixel oder jede SVG-Funktion.

Die weißen Rechtecke auf der Browserseite sind CSS-Hintergründe hinter den Canvas-Elementen. Sie sind keine dem PNG hinzugefügte weiße Farbe. Braucht dein Ergebnis einen undurchsichtigen Hintergrund, zeichne ihn ausdrücklich vor dem Bild und prüfe die exportierte Datei erneut.

## Halte bearbeitbare Masterdatei und PNG getrennt

Das gespeicherte PNG enthält Pixel. Es enthält nicht den ursprünglichen Pfad, Kreis oder bearbeitbaren Innenumriss. Behalte `master.svg` als Vektorquelle und wähle die Canvas-Bitmapabmessungen für das Ziel, das tatsächlich ein PNG braucht. Ein vorhandenes PNG später zu vergrößern stellt seine Quellgeometrie nicht wieder her.

Ein SVG-Dateiname allein beweist auch nicht, dass alle enthaltene Grafik Vektorgeometrie ist. Nutze den [Leitfaden zur Prüfung eingebetteter Rasterbilder](https://perfectvector.com/de/blog/svg-contains-raster-image), wenn eine Datei verknüpfte oder eingebettete Bilder enthält.

Existiert deine Quellgrafik nur als Rasterbild und brauchst du bearbeitbare Konturen, kann [PerfectVectors Bild-zu-Vektor-Workflow](https://perfectvector.com/de/image-to-vector) eine SVG-Masterdatei vorbereiten. Prüfe Umriss, Farben und Öffnungen, bevor du sie in diesem Ladeablauf verwendest. Vektorisierung repariert keine CORS-Header und gewährt keine Canvas-Ausleseberechtigung.

## Häufige Fragen

**Kann ich SVG-Markup direkt an drawImage() übergeben?**
Nein. Dieses Beispiel lädt eine SVG-Datei in ein HTMLImageElement und übergibt das dekodierte Bild an drawImage(). Eine Markup-Zeichenfolge ist nicht dieses Bildobjekt. Halte Dokumentladen und Path2D-Konstruktion aus Pfaddaten getrennt.

**Warum erscheint das Bild, aber der PNG-Export scheitert?**
Ein Bild einer anderen Herkunft, das ohne CORS-Erlaubnis geladen wird, kann das Canvas nach dem Zeichnen verunreinigen. In unserem Fall ohne CORS gelang das Zeichnen, aber sowohl Pixelauslesung als auch Export warfen SecurityError. Prüfe Anfragemodus und Serverantwort, statt eine beschädigte SVG-Geometrie anzunehmen.

**Repariert crossOrigin anonymous jede Bild-URL?**
Nein. Setze es vor src. Der Bildserver muss eine kompatible CORS-Antwort liefern. Dieselbe Grafik scheiterte beim Dekodieren, als anonymous am Endpunkt ohne Erlaubnisheader angefragt wurde.

**Erhält der Canvas-Export als PNG bearbeitbare SVG-Pfade?**
Nein. PNG ist Rasterausgabe. Behalte das ursprüngliche SVG separat, wenn du Pfade, Formen oder Öffnungen bearbeiten musst, und prüfe das PNG bei seiner vorgesehenen Ausgabegröße.

## Quellen

1. [MDN: CanvasRenderingContext2D.drawImage()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage) – Akzeptierte Bildobjekte, Zielgrößen und intrinsische Abmessungen.
2. [MDN: HTMLImageElement.decode()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode) – Promise zur Bildbereitschaft und Zurückweisung bei Abruf-/Dekodierungsfehlern.
3. [MDN: CORS-freigegebene Bilder](https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/CORS_enabled_image) – Herkunftsreinheitsbeschränkungen beim Lesen und Exportieren gezeichneter Bilder.
4. [MDN: HTMLImageElement.crossOrigin](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/crossOrigin) – CORS-Anfragemodus beim Laden von Bildern.
5. [MDN: HTMLCanvasElement.toBlob()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) – PNG-Blob-Erzeugung, null-Ausgabe und SecurityError.
6. [MDN: SVG als Bild](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) – SVG-Bildkontexte und Beschränkungen für externe Ressourcen.

***

Du arbeitest mit einem Rasteroriginal und brauchst bearbeitbare Grafik? [Erstelle mit PerfectVector eine SVG-Masterdatei](https://perfectvector.com/de/image-to-vector), prüfe Umriss und Öffnungen und behalte diese Masterdatei, während du Canvas-Darstellung und exportiertes PNG separat prüfst.

## Explore

- [Read the HTML article](https://perfectvector.com/de/blog/svg-canvas-image-export)
- [SVG-Icons in MapLibre: Pixel und Symbolgröße prüfen](https://perfectvector.com/de/blog/maplibre-svg-symbol-image.md)
- [SVG-Bilder in p5.js: Laden, skalieren und Quelle behalten](https://perfectvector.com/de/blog/p5js-svg-artwork.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
