PerfectVector
Von Irene Kim8 Min. Lesezeit

Canvas Path2D SVG: Pfade in der richtigen Größe nutzen

Verwende SVG-Pfaddaten auf Canvas mit passender viewBox-Transformation, Farben, Aussparungen und Pixeldichte. Folge dem Beispiel und behalte die SVG-Vorlage.

Auf dieser Seite

Übergib das d-Attribut eines Pfads an new Path2D(d) und zeichne es anschließend mit einem Canvas-Kontext. Um das SVG nachzubilden, übernimm auch seine Koordinatenabbildung, Füllung und Füllregel. Der Konstruktor akzeptiert Pfaddaten; er importiert kein SVG-Dokument und wendet dessen viewBox, CSS oder Gruppentransformationen nicht an (MDN: Path2D-Konstruktor).

Das ist wichtig, wenn ein eigenes Icon als SVG richtig aussieht, auf Canvas aber klein, versetzt, schwarz oder innerhalb seiner Aussparung gefüllt erscheint. Das folgende Beispiel behebt diese Unterschiede mit zwei Pfaden und einer explizit angegebenen Einpassungstransformation. Beginne mit vorhandener Vektorgeometrie, wenn du sie hast. Vektorisierung ist nur hilfreich, wenn die wiederzuverwendende Grafik noch als Pixel vorliegt.

Was ein Path2D-Objekt enthält

Betrachte die Pfaddaten als Konturbeschreibung. Andere SVG-Anweisungen stehen außerhalb dieser Zeichenfolge, und dein Canvas-Zeichencode muss die benötigten selbst bereitstellen.

SVG-EingabeAufgabe auf Canvas
d-Wert eines PfadsDie Path2D-Geometrie erstellen
viewBox und angezeigte GrößeDie Zeichentransformation berechnen
fill und fill-rulefillStyle setzen und die Regel an fill() übergeben
transform eines übergeordneten Elements oder PfadsDie entsprechende Transformation separat anwenden
CSS, Verläufe, Masken, Text und BilderDie benötigte Darstellung implementieren oder einen anderen Weg wählen

Das Beispiel verwendet direkte Füllwerte, zwei unmittelbare Kindpfade und keine anderen SVG-Funktionen. Es ist bewusst klein genug zum Prüfen. Wenn du seine Extraktionsschleife in einen beliebigen SVG-Importer kopierst, gehen geerbte Stile und nicht unterstützte Elemente verloren.

Die Quelle mit einem nicht konfigurierten Canvas vergleichen

Dieses eigene Emblem hat einen abgerundeten petrolfarbenen Körper, eine orange Spitze und eine quadratische Aussparung. Sein viewBox beginnt bei (20, 10), nicht bei (0, 0). Der innere Teilpfad verläuft in derselben Richtung wie die äußere Grenze, weshalb die angegebene Regel evenodd wichtig ist.

Setze dieses SVG und ein Canvas in eine HTML-Seite:

<svg id="source" xmlns="http://www.w3.org/2000/svg"
     viewBox="20 10 120 80" width="240" height="160">
  <path fill="#126d70" fill-rule="evenodd"
        d="M40 20 H90 Q110 20 110 40 V60 Q110 80 90 80 H40 Q30 80 30 70 V30 Q30 20 40 20 Z M50 35 H80 V60 H50 Z"/>
  <path fill="#f19b38" d="M115 25 L135 50 L115 75 Z"/>
</svg>
<canvas id="result"></canvas>

Wenn du über die beiden d-Werte iterierst und ohne weitere Einstellungen ctx.fill(new Path2D(d)) aufrufst, verwendet die Geometrie Canvas-Koordinaten sowie die Standardfarbe und -füllregel. Sie übernimmt das SVG-Erscheinungsbild nicht automatisch. Canvas-fill() akzeptiert einen Pfad und eine explizit angegebene Regel evenodd oder nonzero; nonzero ist der Standard (MDN: fill()).

Browservergleich eines SVG-Emblems, einer kleinen schwarzen unbearbeiteten Path2D-Darstellung mit gefüllter Aussparung und einer korrekt eingepassten zweifarbigen Canvas-Darstellung
Dieselben von Hand geschriebenen Pfade im Browser: SVG-Referenz, unverarbeitetes Path2D und explizites Einpassen mit wiederhergestellten Farben und evenodd. Die Tabelle zeigt Bitmap-Abmessungen für vier Größen- und DPR-Eingaben.

Methode: Wir haben dieses von Hand geschriebene SVG im Browser gerendert, seine zwei Pfade über beide Canvas-Wege gezeichnet und den veröffentlichten Code in einer separaten HTML-Seite erneut ausgeführt. Der Screenshot ist tatsächliche Browserausgabe. Er zeigt den Umgang mit Koordinaten und Farben, keine PerfectVector-Konvertierung.

Den viewBox auf das Canvas abbilden

Das standardmäßige seitenverhältniserhaltende SVG-Verhalten passt den viewBox in seinen Darstellungsbereich ein und zentriert ihn. Die SVG-Spezifikation der Koordinatensysteme definiert diese Abbildung. Bilde für dieses flache Beispiel xMidYMid meet mit einer gleichmäßigen Skalierung und einer Verschiebung nach:

scale = min(cssWidth / viewBoxWidth, cssHeight / viewBoxHeight)
tx = (cssWidth - viewBoxWidth * scale) / 2 - viewBoxX * scale
ty = (cssHeight - viewBoxHeight * scale) / 2 - viewBoxY * scale

Die letzten Terme entfernen den Ursprung ungleich null. Bei 240 × 160 ist scale 2, tx -40 und ty -20. Bei 300 × 120 wird scale zu 1.5; der eingepasste, 180 Pixel breite viewBox erhält auf jeder Seite 60 Pixel horizontalen Freiraum. Die Verschiebung beträgt deshalb nach Berücksichtigung des Quellursprungs (30, -15).

Verwende das folgende Skript nach dem HTML oben. Es verarbeitet die direkten Pfadattribute dieses Beispiels, zeichnet das gesamte Canvas neu und trennt CSS-Größe von Bitmap-Größe:

const source = document.querySelector("#source");
const vb = source.viewBox.baseVal;
const layers = [...source.querySelectorAll("path")].map(el => ({
  path: new Path2D(el.getAttribute("d")),
  fill: el.getAttribute("fill"),
  rule: el.getAttribute("fill-rule") || "nonzero"
}));
 
function draw(canvas, cssWidth, cssHeight, dpr = window.devicePixelRatio || 1) {
  canvas.style.width = `${cssWidth}px`;
  canvas.style.height = `${cssHeight}px`;
  canvas.width = Math.round(cssWidth * dpr);
  canvas.height = Math.round(cssHeight * dpr);
  const ctx = canvas.getContext("2d");
  const scale = Math.min(cssWidth / vb.width, cssHeight / vb.height);
  const tx = (cssWidth - vb.width * scale) / 2 - vb.x * scale;
  const ty = (cssHeight - vb.height * scale) / 2 - vb.y * scale;
  const px = canvas.width / cssWidth;
  const py = canvas.height / cssHeight;
  ctx.setTransform(px * scale, 0, 0, py * scale, px * tx, py * ty);
  for (const layer of layers) {
    ctx.fillStyle = layer.fill;
    ctx.fill(layer.path, layer.rule);
  }
}
 
draw(document.querySelector("#result"), 240, 160);
 

Das Setzen von canvas.width und canvas.height löscht und setzt den Kontext zurück. Die Funktion setzt anschließend die vollständige Transformation und zeichnet jede Ebene erneut, sodass wiederholte Aufrufe keine Skalierung ansammeln. Sie setzt einen gültigen viewBox mit positiver Breite und Höhe sowie positive angeforderte Abmessungen voraus.

px und py verwenden die tatsächlichen gerundeten Bitmap-Abmessungen. Dadurch bleiben CSS-Koordinaten auf die zugewiesenen Pixel abgebildet, auch wenn die angeforderte Dichte nicht ganzzahlige Abmessungen ergibt. MDNs devicePixelRatio-Beispiel erklärt, warum Canvas-Anzeigegröße und Pixelabmessungen getrennt behandelt werden müssen.

Größe und Pixeldichte getrennt prüfen

Wir haben bei zwei CSS-Größen die DPR-Werte 1 und 2 explizit an dieselbe Funktion übergeben. Das sind kontrollierte Dichteeingaben, keine Behauptung, dass wir zwei physische Geräte getestet haben. Das vom Browser gemeldete Geräte-Pixelverhältnis für den Standardaufruf war 2.

CSS-GrößeDPR-ArgumentBeobachtete Canvas-Bitmap
240 × 1601240 × 160
240 × 1602480 × 320
300 × 1201300 × 120
300 × 1202600 × 240

Die Mitte der Aussparung blieb in allen vier Fällen transparent. Eine höhere Dichte verändert die Bitmap-Auflösung; sie behebt keine falsche Transformation und stellt keine fehlende Füllregel wieder her. Zeichne neu, wenn sich die vorgesehenen CSS-Abmessungen oder das Geräte-Pixelverhältnis ändern. Eine reine CSS-Vergrößerung streckt die bereits auf dem Canvas vorhandene Bitmap.

Wenn die Quelle schon vor dem Canvas falsch ist, verwende die SVG-Größen- und viewBox-Prüfungen. Wenn nur das Canvas falsch ist, vergleiche zunächst seine Transformation und Farbverarbeitung mit der funktionierenden SVG-Referenz.

Die Quelle erhalten und den richtigen Importweg wählen

Behalte die SVG-Vorlage und ihre Attribute neben abgeleiteten Pfaddaten. Eine Path2D-Zeichenroutine ist hilfreich, wenn du eine kleine Menge Konturen und deren Gestaltung kontrollierst. Wenn du bei einem komplexen SVG nur sein vom Browser gerendertes Erscheinungsbild benötigst, kann das Laden und Zeichnen als Bild vermeiden, dass du jede Funktion nachbauen musst. Auch dieser Weg zeichnet in die Canvas-Bitmap.

Das Speichern der Canvas-Ausgabe als PNG erzeugt ein Rasterbild, auch wenn die Zeichnung mit Vektorpfaden begann. Die Canvas-Export-API erzeugt einen Bild-Blob; PNG-Unterstützung ist vorgeschrieben (MDN: toBlob()). Behalte SVG für spätere Pfadbearbeitung. Ebenso kann eine SVG-Datei ein Rasterbild statt nützlicher Pfaddaten enthalten; die Diagnose eingebetteter Bilder hilft, diese Fälle zu unterscheiden.

PerfectVector eignet sich, wenn von deinem eigenen Icon nur ein PNG oder JPG übrig ist und du wiederverwendbare Konturen benötigst. Konvertiere dieses Bild in SVG und prüfe dann seine Silhouette, getrennten Farben und kleinen Aussparungen, bevor du Pfade für Canvas extrahierst. Eine saubere SVG-Vorlage sollte direkt in den Vorbereitungsschritt gehen. Nachzeichnen implementiert keine viewBox-Abbildung, kopiert kein CSS und macht ein Canvas-PNG nicht als Vektoren bearbeitbar.

Lege bei einer ganzen Icon-Familie das gemeinsame UI-Kit-Raster und die Farbregeln fest, bevor du jede Zeichenroutine einbindest. Weitere Beispiele zur SVG-Vorbereitung findest du im Blog.

Bevor du die Zeichnung in deiner Oberfläche verwendest

  • Prüfe die SVG-Referenz in denselben Anzeigeabmessungen wie das Canvas.
  • Bestätige den viewBox-Ursprung ebenso wie Breite und Höhe.
  • Übertrage Farben und vorgesehene Füllregel; prüfe jede Aussparung.
  • Berücksichtige Gruppentransformationen, statt nur d zu kopieren.
  • Lies die tatsächlichen Werte von canvas.width und canvas.height und teste dann die größte vorgesehene Anzeigegröße.
  • Behalte die SVG-Vorlage und stelle einen zur Oberfläche passenden zugänglichen Namen oder umgebenden Text bereit.

FAQ

Kann Path2D eine vollständige SVG-Datei importieren? Nein. Seine Zeichenfolgeneingabe besteht aus SVG-Pfaddaten, etwa dem Wert des d-Attributs eines Pfads. Dokumentstruktur, viewBox-Abbildung, Stile und Gruppentransformationen benötigen separate Verarbeitung.

Warum wurde die Aussparung meines SVG auf Canvas gefüllt? Prüfe Füllregel und Teilpfadrichtungen. Dieses Beispiel benötigt evenodd, während Canvas-fill standardmäßig nonzero verwendet. Übergib beim Füllen des Path2D-Objekts die vorgesehene Regel.

Erhält das Zeichnen von SVG-Pfaden auf Canvas einen Vektorexport? Die Pfade bleiben in deinem Programm wiederverwendbare Zeichenanweisungen, aber der Canvas-Export als PNG erzeugt Pixel. Behalte das ursprüngliche SVG für Bearbeitung und Vektorübergabe.

Quellen

  1. MDN — Path2D-Konstruktor — Definiert die vom Konstruktor akzeptierte Pfaddatenzeichenfolge.
  2. W3C — SVG-Koordinatensysteme — Definiert viewBox-Ursprung, Darstellungsbereichsabbildung und seitenverhältniserhaltende Ausrichtung.
  3. MDN — Canvas fill() — Dokumentiert das Füllen von Pfaden und die Regeln evenodd und nonzero.
  4. MDN — devicePixelRatio — Erklärt CSS-Anzeigegröße und Canvas-Bitmap-Auflösung.
  5. MDN — Canvas toBlob() — Dokumentiert den Rasterbildexport eines Canvas.

Du hast nur ein Rastericon? Bereite sein SVG mit PerfectVector vor, prüfe Kontur und Aussparungen und vergleiche dann die Canvas-Zeichnung mit diesem SVG in deinen tatsächlichen Oberflächengrößen.

Mehr aus dem Blog

Starte mit einer sauberen SVG,
die leichter zu bearbeiten ist