PerfectVector
Oleh Irene Kim8 menit baca

SVG Path2D Canvas: Gunakan Ulang Path pada Ukuran yang Tepat

Gunakan ulang data path SVG pada canvas dengan transformasi viewBox, warna, lubang, dan kepadatan piksel yang tepat. Ikuti contoh orisinal dan pertahankan master SVG yang dapat diedit.

Di halaman ini

Berikan atribut d sebuah path ke new Path2D(d), lalu gambar dengan konteks canvas. Agar sesuai dengan SVG, sertakan juga pemetaan koordinat, pewarnaan, dan aturan isiannya. Konstruktor menerima data path; konstruktor tidak mengimpor dokumen SVG atau menerapkan viewBox, CSS, maupun transformasi grup dokumen tersebut (konstruktor Path2D MDN).

Hal ini penting ketika ikon khusus terlihat benar sebagai SVG tetapi menjadi kecil, bergeser, hitam, atau lubangnya terisi saat berada di canvas. Contoh di bawah memperbaiki perbedaan tersebut dengan dua path dan transformasi penyesuaian eksplisit. Mulailah dengan geometri vektor yang sudah ada jika Anda memilikinya. Vektorisasi berguna hanya ketika artwork yang ingin Anda gunakan ulang masih berupa piksel.

Apa yang dibawa objek Path2D

Anggap data path sebagai deskripsi kontur. Instruksi SVG lainnya berada di luar string itu, dan kode gambar canvas Anda harus menyediakan instruksi yang dibutuhkannya.

Input SVGTanggung jawab canvas
Nilai d sebuah pathBangun geometri Path2D
viewBox dan ukuran tampilanHitung transformasi gambar
fill dan fill-ruleAtur fillStyle dan berikan aturan ke fill()
transform induk atau pathTerapkan transformasi setara secara terpisah
CSS, gradien, mask, teks, dan gambarImplementasikan rendering yang diperlukan atau pilih jalur lain

Sampel menggunakan isian literal, dua path anak langsung, dan tidak ada fitur SVG lain. Sampel ini sengaja cukup kecil untuk diperiksa. Menyalin loop ekstraksinya ke importer SVG sembarang akan menghilangkan gaya yang diwariskan dan elemen yang tidak didukung.

Bandingkan sumber dengan canvas yang belum dikonfigurasi

Lambang orisinal ini memiliki badan hijau kebiruan membulat, ujung oranye, dan bukaan persegi. viewBox-nya dimulai pada (20, 10), bukan (0, 0). Subpath dalam berjalan searah dengan batas luar, sehingga aturan evenodd yang dideklarasikan menjadi penting.

Letakkan SVG ini dan canvas ke dalam halaman HTML:

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

Jika Anda melakukan loop pada dua nilai d dan memanggil ctx.fill(new Path2D(d)) tanpa mengatur hal lain, geometri menggunakan koordinat canvas serta pewarnaan dan aturan isian default. Geometri tidak otomatis memperoleh tampilan SVG. fill() canvas menerima path dan aturan evenodd atau nonzero eksplisit; nonzero adalah default (fill() MDN).

Perbandingan browser antara lambang SVG, rendering Path2D mentah berwarna hitam dan kecil dengan bukaan terisi, serta rendering canvas dua warna yang disesuaikan dengan benar
Path buatan tangan yang sama dalam browser: referensi SVG, Path2D mentah, dan penyesuaian eksplisit dengan pewarnaan dan evenodd dipulihkan. Tabel mencatat dimensi bitmap untuk empat input ukuran dan DPR.

Metode: kami merender SVG buatan tangan ini di browser, menggambar dua path-nya melalui kedua jalur canvas, dan menjalankan ulang kode yang dipublikasikan dalam halaman HTML terpisah. Tangkapan layar merupakan output browser sebenarnya. Tangkapan itu memperagakan penanganan koordinat dan pewarnaan, bukan konversi PerfectVector.

Petakan viewBox ke dalam canvas

Perilaku default SVG yang mempertahankan aspek menyesuaikan viewBox agar muat di dalam viewport dan memusatkannya. Spesifikasi sistem koordinat SVG mendefinisikan pemetaan itu. Untuk contoh datar ini, terapkan kembali xMidYMid meet dengan satu skala seragam dan translasi:

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

Suku terakhir menghilangkan titik asal bukan nol. Pada 240 × 160, skalanya adalah 2, tx adalah -40, dan ty adalah -20. Pada 300 × 120, skala menjadi 1.5; viewBox yang disesuaikan dengan lebar 180 piksel mendapat ruang horizontal 60 piksel di setiap sisi. Karena itu, translasinya adalah (30, -15) setelah memperhitungkan titik asal sumber.

Gunakan skrip berikut setelah HTML di atas. Skrip menangani atribut path langsung dari sampel ini, menggambar ulang seluruh canvas, dan memisahkan ukuran CSS dari ukuran bitmap:

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

Mengatur canvas.width dan canvas.height membersihkan dan mereset konteks. Fungsi kemudian mengatur transformasi lengkap dan menggambar ulang setiap lapisan, sehingga pemanggilan berulang tidak mengakumulasi skala. Fungsi mengasumsikan viewBox valid dengan lebar dan tinggi positif serta dimensi yang diminta positif.

px dan py menggunakan dimensi bitmap sebenarnya yang telah dibulatkan. Hal itu menjaga koordinat CSS tetap dipetakan ke piksel yang dialokasikan meskipun kepadatan yang diminta menghasilkan dimensi pecahan. Contoh devicePixelRatio MDN menjelaskan mengapa ukuran tampilan canvas dan dimensi piksel memerlukan penanganan terpisah.

Periksa ukuran dan kepadatan piksel secara terpisah

Kami memberikan nilai DPR 1 dan 2 secara eksplisit ke fungsi yang sama pada dua ukuran CSS. Ini adalah input kepadatan terkontrol, bukan klaim bahwa kami menguji dua perangkat fisik. Rasio piksel perangkat yang dilaporkan browser untuk pemanggilan default adalah 2.

Ukuran CSSArgumen DPRBitmap canvas yang diamati
240 × 1601240 × 160
240 × 1602480 × 320
300 × 1201300 × 120
300 × 1202600 × 240

Pusat bukaan tetap transparan dalam keempat kasus. Kepadatan lebih tinggi mengubah resolusi bitmap; hal itu tidak memperbaiki transformasi yang salah atau memulihkan aturan isian yang hilang. Gambar ulang ketika dimensi CSS yang dimaksudkan atau rasio piksel perangkat berubah. Pembesaran melalui CSS saja meregangkan bitmap yang sudah ada pada canvas.

Jika sumber sudah salah sebelum mencapai canvas, gunakan pemeriksaan ukuran SVG dan viewBox. Jika hanya canvas yang salah, bandingkan transformasi dan penanganan pewarnaannya dengan referensi SVG yang berfungsi terlebih dahulu.

Pertahankan sumber dan pilih jalur impor yang tepat

Simpan master SVG dan atributnya bersama data path turunannya. Rutinitas gambar Path2D berguna ketika Anda mengendalikan sejumlah kecil kontur dan gayanya. Untuk SVG kompleks yang hanya perlu Anda tampilkan seperti hasil rendering browser, memuatnya sebagai gambar dan menggambar gambar itu dapat menghindari pembangunan ulang setiap fitur. Jalur tersebut tetap menggambar ke bitmap canvas.

Menyimpan output canvas sebagai PNG membuat gambar raster, meskipun gambarnya dimulai dari path vektor. API ekspor canvas menghasilkan blob gambar; dukungan PNG diwajibkan (toBlob() MDN). Pertahankan SVG untuk pengeditan path di kemudian hari. Demikian pula, file SVG dapat berisi gambar raster alih-alih data path yang berguna; diagnosis gambar tertanam membantu membedakan kasus tersebut.

PerfectVector sesuai ketika hanya PNG atau JPG dari ikon khusus Anda yang tersisa dan Anda membutuhkan kontur yang dapat digunakan ulang. Konversikan gambar tersebut menjadi SVG, lalu periksa siluet, warna terpisah, dan bukaan kecilnya sebelum mengekstrak path untuk canvas. Master SVG yang bersih sebaiknya langsung masuk ke langkah persiapan. Penelusuran tidak mengimplementasikan pemetaan viewBox, menyalin CSS, atau membuat PNG canvas dapat diedit sebagai vektor.

Untuk seluruh keluarga ikon, tetapkan grid kit UI bersama dan aturan pewarnaan sebelum menghubungkan setiap rutinitas gambar. Contoh persiapan SVG lainnya ada di blog.

Sebelum Anda menggunakan gambar dalam antarmuka

  • Periksa referensi SVG pada dimensi tampilan yang sama dengan canvas.
  • Konfirmasi titik asal viewBox serta lebar dan tingginya.
  • Pindahkan pewarnaan dan aturan isian yang dimaksudkan; periksa setiap bukaan.
  • Perhitungkan transformasi grup alih-alih hanya menyalin d.
  • Baca canvas.width dan canvas.height sebenarnya, lalu uji ukuran tampilan terbesar yang dimaksudkan.
  • Pertahankan master SVG dan sediakan nama aksesibel atau teks di sekitarnya yang sesuai dengan antarmuka.

FAQ

Dapatkah Path2D mengimpor seluruh file SVG? Tidak. Input string-nya adalah data path SVG, seperti nilai atribut d sebuah path. Struktur dokumen, pemetaan viewBox, gaya, dan transformasi grup memerlukan penanganan terpisah.

Mengapa lubang SVG saya terisi pada canvas? Periksa aturan isian dan arah subpath. Contoh ini memerlukan evenodd, sedangkan isian canvas secara default menggunakan nonzero. Berikan aturan yang dimaksudkan ketika mengisi objek Path2D.

Apakah menggambar path SVG pada canvas mempertahankan ekspor vektor? Path tetap menjadi instruksi gambar yang dapat digunakan ulang dalam program Anda, tetapi mengekspor canvas sebagai PNG menghasilkan piksel. Simpan SVG asli untuk pengeditan dan penyerahan vektor.

Sources

  1. MDN — Konstruktor Path2D — Mendefinisikan string data path yang diterima konstruktor.
  2. W3C — Sistem koordinat SVG — Mendefinisikan titik asal viewBox, pemetaan viewport, dan perataan yang mempertahankan aspek.
  3. MDN — fill() Canvas — Mendokumentasikan pengisian path serta aturan evenodd dan nonzero.
  4. MDN — devicePixelRatio — Menjelaskan ukuran tampilan CSS dan resolusi bitmap canvas.
  5. MDN — toBlob() Canvas — Mendokumentasikan ekspor gambar raster dari canvas.

Hanya memiliki ikon raster? Siapkan SVG-nya dengan PerfectVector, periksa kontur dan bukaannya, lalu bandingkan gambar canvas dengan SVG tersebut pada ukuran antarmuka Anda yang sebenarnya.

Lebih banyak dari blog

Mulai dengan SVG yang lebih rapi
dan lebih mudah diedit