PerfectVector
Yazan Irene Kim8 dk okuma

Canvas Path2D SVG: Yolları doğru boyutta yeniden kullanın

SVG yol verilerini doğru viewBox dönüşümü, renkler, delikler ve piksel yoğunluğuyla canvas’ta yeniden kullanın. Özgün örneği izleyin, düzenlenebilir SVG ana dosyasını saklayın.

Bu sayfada

Bir yolun d özniteliğini new Path2D(d) çağrısına verin, ardından bir canvas bağlamıyla çizin. SVG’yle eşleşmesi için koordinat eşlemesini, boyama özelliklerini ve dolgu kuralını da aktarın. Kurucu yol verisi kabul eder; bir SVG belgesini içe aktarmaz veya belgenin viewBox, CSS ya da grup dönüşümlerini uygulamaz (MDN Path2D kurucusu).

Bu ayrım, özel bir simge SVG olarak doğru görünürken canvas’ta küçük, kaymış, siyah veya açıklığı dolmuş olarak göründüğünde önemlidir. Aşağıdaki örnek, iki yol ve açıkça tanımlanmış bir sığdırma dönüşümüyle bu farkları düzeltir. Elinizde mevcut vektör geometrisi varsa onunla başlayın. Vektörleştirme yalnızca yeniden kullanmanız gereken görsel hâlâ piksellerden oluşuyorsa faydalıdır.

Bir Path2D nesnesi neleri taşır?

Yol verisini konturun tanımı olarak düşünün. Diğer SVG talimatları bu dizenin dışında bulunur ve canvas çizim kodunuz, ihtiyaç duyduğu talimatları sağlamalıdır.

SVG girdisiCanvas’ın sorumluluğu
Bir yolun d değeriPath2D geometrisini oluşturmak
viewBox ve görüntülenen boyutÇizim dönüşümünü hesaplamak
fill ve fill-rulefillStyle ayarlamak ve kuralı fill() çağrısına vermek
Üst öğenin veya yolun transform değeriEşdeğer dönüşümü ayrıca uygulamak
CSS, degradeler, maskeler, metin ve görsellerGereken çizim işlemlerini uygulamak veya başka bir yöntem seçmek

Örnek, doğrudan belirtilmiş dolgu renkleri ve doğrudan alt öğe olan iki yol kullanır; başka SVG özelliği içermez. İncelenebilmesi için özellikle küçük tutulmuştur. Öznitelikleri çıkaran döngüsünü genel amaçlı bir SVG içe aktarıcısına kopyalamak, kalıtılan stilleri ve desteklenmeyen öğeleri kaybettirir.

Kaynağı yapılandırılmamış bir canvas ile karşılaştırın

Bu özgün amblemde yuvarlatılmış turkuaz bir gövde, turuncu bir uç ve kare bir açıklık vardır. viewBox başlangıcı (0, 0) değil, (20, 10) noktasıdır. İç alt yol dış sınırla aynı yönde ilerlediği için belirtilen evenodd kuralı önemlidir.

Bu SVG’yi ve bir canvas öğesini bir HTML sayfasına yerleştirin:

<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>

İki d değeri üzerinde döngü kurup başka hiçbir şey ayarlamadan ctx.fill(new Path2D(d)) çağırırsanız geometri, canvas koordinatlarını ve varsayılan boyama ve dolgu kuralını kullanır. SVG’nin görünümünü otomatik olarak edinmez. Canvas fill(), hem bir yol hem de açıkça belirtilmiş bir evenodd veya nonzero kuralı kabul eder; varsayılan nonzero değeridir (MDN fill()).

Bir SVG ambleminin, açıklığı dolmuş küçük ve siyah ham Path2D çiziminin ve doğru sığdırılmış iki renkli canvas çiziminin tarayıcıdaki karşılaştırması
Tarayıcıda aynı elle yazılmış yollar: SVG referansı, ham Path2D ve boyama özellikleri ile evenodd kuralı geri yüklenmiş, açıkça tanımlanmış sığdırma. Tablo, dört boyut ve DPR girdisi için alttaki raster görüntünün boyutlarını gösterir.

Yöntem: elle yazılmış bu SVG’yi tarayıcıda çizdik, iki yolunu her iki canvas yöntemiyle çizdik ve yayımlanan kodu ayrı bir HTML sayfasında yeniden çalıştırdık. Ekran görüntüsü gerçek tarayıcı çıktısıdır. PerfectVector dönüşümünü değil, koordinatların ve boyama özelliklerinin uygulanmasını gösterir.

viewBox’ı canvas’a eşleyin

SVG’nin varsayılan en-boy oranını koruyan davranışı, viewBox’ı görüntüleme alanına sığdırır ve ortalar. SVG koordinat sistemi belirtimi, bu eşlemeyi tanımlar. Bu düz örnekte xMidYMid meet davranışını her iki eksende aynı ölçek katsayısını kullanıp bir öteleme uygulayarak yeniden oluşturun:

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

Son terimler, sıfırdan farklı başlangıç noktasını kaldırır. 240 × 160 boyutunda ölçek 2, tx değeri -40 ve ty değeri -20 olur. 300 × 120 boyutunda ölçek 1.5 olur; sığdırılan 180 piksel genişliğindeki viewBox’ın her iki yanında yatay olarak 60 piksel boşluk kalır. Kaynağın başlangıç noktası hesaba katıldığında öteleme (30, -15) olur.

Aşağıdaki betiği yukarıdaki HTML’den sonra kullanın. Bu örneğin doğrudan yol özniteliklerini işler, canvas’ın tamamını yeniden çizer ve CSS boyutunu alttaki raster görüntünün boyutundan ayırır:

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);
 

canvas.width ve canvas.height değerlerini ayarlamak, bağlamı temizler ve sıfırlar. Ardından işlev, dönüşümün tamamını ayarlar ve her katmanı yeniden boyar; böylece tekrarlanan çağrılarda ölçek birikmez. Genişliği ve yüksekliği pozitif olan geçerli bir viewBox ve pozitif hedef boyutlar varsayar.

px ve py, yuvarlanmış gerçek raster görüntü boyutlarını kullanır. Böylece istenen yoğunluk kesirli boyutlar üretse bile CSS koordinatları, ayrılan piksellere eşlenmiş kalır. MDN’nin devicePixelRatio örneği, canvas’ın görüntüleme boyutuyla piksel boyutlarının neden ayrı ele alınması gerektiğini açıklar.

Boyutu ve piksel yoğunluğunu ayrı kontrol edin

Aynı işleve iki CSS boyutunda 1 ve 2 DPR değerlerini açıkça verdik. Bunlar kontrollü yoğunluk girdileridir; iki fiziksel cihazı test ettiğimiz iddiası değildir. Varsayılan çağrı için tarayıcının bildirdiği cihaz piksel oranı 2 idi.

CSS boyutuDPR argümanıGözlenen canvas raster görüntüsü
240 × 1601240 × 160
240 × 1602480 × 320
300 × 1201300 × 120
300 × 1202600 × 240

Dört durumda da açıklığın merkezi saydam kaldı. Daha yüksek yoğunluk, alttaki raster görüntünün çözünürlüğünü değiştirir; yanlış bir dönüşümü düzeltmez veya eksik bir dolgu kuralını geri getirmez. Hedef CSS boyutları veya cihaz piksel oranı değiştiğinde yeniden çizin. Yalnızca CSS ile büyütmek, canvas üzerindeki mevcut raster görüntüyü esnetir.

Kaynak, canvas’a ulaşmadan önce zaten yanlışsa SVG boyutu ve viewBox kontrollerini kullanın. Yalnızca canvas yanlışsa önce dönüşümünü ve boyama özelliklerini uygulama biçimini çalışan SVG referansıyla karşılaştırın.

Kaynağı koruyun ve doğru içe aktarma yöntemini seçin

SVG ana dosyasını ve özniteliklerini, ondan türetilen yol verileriyle birlikte saklayın. Küçük bir kontur kümesini ve stillerini kontrol ettiğinizde bir Path2D çizim yordamı faydalıdır. Yalnızca tarayıcıda çizilmiş görünümüne ihtiyaç duyduğunuz karmaşık bir SVG için dosyayı görsel olarak yükleyip o görseli çizmek, her özelliği yeniden oluşturmayı önleyebilir. Bu yöntem de canvas’ın raster görüntüsüne çizim yapar.

Canvas çıktısını PNG olarak kaydetmek, çizim vektör yollarıyla başlamış olsa bile raster bir görüntü oluşturur. Canvas dışa aktarma API’si bir görsel blob’u üretir; PNG desteği zorunludur (MDN toBlob()). Yolları daha sonra düzenlemek için SVG’yi saklayın. Benzer şekilde bir SVG dosyası, kullanılabilir yol verileri yerine raster bir görüntü içerebilir; gömülü görsel tanılama rehberi bu durumları ayırt etmenize yardımcı olur.

Özel simgenizin yalnızca PNG veya JPG’si kaldığında ve yeniden kullanılabilir konturlara ihtiyaç duyduğunuzda PerfectVector uygundur. Bu görseli SVG’ye dönüştürün, ardından canvas için yolları çıkarmadan önce silüetini, ayrı renklerini ve küçük açıklıklarını inceleyin. Temiz bir SVG ana dosyası doğrudan hazırlık adımına geçmelidir. Vektörleştirme, viewBox eşlemesini uygulamaz, CSS’i kopyalamaz veya bir canvas PNG’sini vektör olarak düzenlenebilir hâle getirmez.

Bir simge ailesinin tamamı için her çizim yordamını bağlamadan önce ortak arayüz kiti ızgarasını ve boyama kurallarını belirleyin. Daha fazla SVG hazırlama örneği blogda bulunur.

Çizimi arayüzünüzde kullanmadan önce

  • SVG referansını canvas ile aynı görüntüleme boyutlarında kontrol edin.
  • viewBox’ın genişliği ve yüksekliğiyle birlikte başlangıç noktasını da doğrulayın.
  • Boyama özelliklerini ve amaçlanan dolgu kuralını aktarın; her açıklığı inceleyin.
  • Yalnızca d değerini kopyalamak yerine grup dönüşümlerini hesaba katın.
  • Gerçek canvas.width ve canvas.height değerlerini okuyun, ardından hedeflenen en büyük görüntüleme boyutunu test edin.
  • SVG ana dosyasını saklayın ve arayüze uygun bir erişilebilir ad veya çevreleyen metin sağlayın.

Sık sorulan sorular

Path2D bir SVG dosyasının tamamını içe aktarabilir mi? Hayır. Dize girdisi, bir yolun d özniteliğinin değeri gibi SVG yol verisidir. Belge yapısı, viewBox eşlemesi, stiller ve grup dönüşümleri ayrıca ele alınmalıdır.

SVG’mdeki delik canvas’ta neden doldu? Dolgu kuralını ve alt yolların yönlerini kontrol edin. Bu örnek evenodd gerektirirken canvas dolgusunun varsayılanı nonzero değeridir. Path2D nesnesini doldururken amaçlanan kuralı verin.

SVG yollarını canvas’a çizmek, vektör dışa aktarımını korur mu? Yollar, programınızda yeniden kullanılabilir çizim talimatları olarak kalır; ancak canvas’ı PNG olarak dışa aktarmak piksel üretir. Düzenleme ve vektör teslimi için özgün SVG’yi saklayın.

Kaynaklar

  1. MDN — Path2D constructor — Kurucunun kabul ettiği yol verisi dizesini tanımlar.
  2. W3C — SVG coordinate systems — viewBox başlangıç noktasını, görüntüleme alanı eşlemesini ve en-boy oranını koruyan hizalamayı tanımlar.
  3. MDN — Canvas fill() — Yol dolgusunu ve evenodd ile nonzero kurallarını belgeler.
  4. MDN — devicePixelRatio — CSS görüntüleme boyutunu ve canvas’ın raster görüntü çözünürlüğünü açıklar.
  5. MDN — Canvas toBlob() — Canvas’tan raster görüntü dışa aktarmayı belgeler.

Elinizde yalnızca raster bir simge mi var? SVG’sini PerfectVector ile hazırlayın, konturunu ve açıklıklarını kontrol edin, ardından canvas çizimini gerçek arayüz boyutlarınızda bu SVG ile karşılaştırın.

Bloga daha fazlası

Düzenlemesi daha kolay,
daha temiz bir SVG ile başlayın