Empat chapter sebelumnya membekali kita dua teknologi gambar: SVG menyimpan objek di DOM, canvas melukis piksel lewat JavaScript. Keduanya tidak saling menggantikan; masing-masing unggul pada pekerjaan berbeda. Chapter ini merangkum keputusannya: matriks cepat, tabel perbandingan, keputusan inline versus file, dan studi kasus satu visual dua cara.
Matriks Keputusan Cepat #
Kebutuhan paling sering muncul dapat dipetakan seketika:
- Ikon, logo, dan diagram statis: SVG, karena ringan, tajam, dan dapat di-style;
- Gambar yang harus tetap jernih saat di-zoom: SVG, karena browser merender ulang dari deskripsi vektor;
- Game 2D dan simulasi partikel: canvas, karena gambar ulang tiap frame adalah pola bawaannya;
- Puluhan ribu titik data atau edit tingkat piksel: canvas, karena ribuan objek SVG menumpuk DOM;
- Chart data: keduanya mungkin; SVG untuk chart kecil yang perlu aksesibel dan interaktif, canvas untuk dataset besar yang hanya dilihat.
Aturan praktisnya: makin banyak objek yang harus tetap bernyawa sebagai elemen, makin cocok SVG; makin banyak piksel yang dirender tiap frame, makin cocok canvas.
Tabel Perbandingan Lengkap #
| Aspek | SVG | Canvas |
|---|---|---|
| Representasi | Objek vektor yang tersimpan di DOM | Piksel hasil gambar |
| Cara menggambar | Markup XML yang dideklarasikan | Perintah JavaScript yang dieksekusi |
| Akses per bentuk | Setiap bentuk bisa dipilih dan diubah | Tidak ada objek; satu elemen canvas saja |
| Aksesibilitas | Nama lewat title, desc, role | Terbatas: fallback content dan aria-label |
| Animasi | CSS, SMIL, atau JS mengubah atribut | Loop gambar ulang tiap frame |
| Interaksi per objek | Event pada setiap bentuk | Hit-testing manual di koordinat kursor |
| Performa banyak objek | Menurun saat DOM menumpuk | Stabil bila jumlah gambar per frame terkendali |
| Ketajaman saat zoom | Tetap tajam | Mengikuti resolusi piksel kanvas |
Dua baris terakhir sering menentukan. Diagram organisasi dengan ratusan kotak yang perlu diklik tetap nyaman di SVG; peta bintang dengan puluhan ribu titik hanya realistis di canvas.
Keputusan Ulang: Inline atau img #
Setelah memilih SVG, keputusan kedua perlu diulang dengan kerangka ringkas:
- Perlu styling CSS halaman atau akses DOM: inline SVG;
- Dipakai lintas halaman dan menguntungkan cache: file SVG lewat
img; - Berasal dari pihak ketiga: lewat
img, karena script di dalamnya tidak dijalankan.
Studi Kasus: Satu Visual, Dua Cara #
Ring progres menampakkan karakter keduanya dalam satu visual: lingkaran abu penuh, busur hijau 70% keliling, dan teks persentase di tengah. File berikut menggambar visual yang sama dua kali:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ring Progres: SVG dan Canvas</title>
</head>
<body>
<h1>Progres Unduhan: 70%</h1>
<p>Visual yang sama, digambar dengan dua teknologi berbeda.</p>
<figure>
<svg viewBox="0 0 120 120" width="120" height="120" role="img" aria-label="Ring progres 70 persen, versi SVG">
<circle cx="60" cy="60" r="45" fill="none" stroke="#f3f4f6" stroke-width="12"/>
<circle cx="60" cy="60" r="45" fill="none" stroke="#1a6b54" stroke-width="12" stroke-linecap="round" stroke-dasharray="198 283" transform="rotate(-90 60 60)"/>
<text x="60" y="67" text-anchor="middle" font-size="20" font-weight="bold" fill="#1f2937">70%</text>
</svg>
<figcaption>Versi SVG: dua lingkaran dan satu teks di dalam DOM.</figcaption>
</figure>
<figure>
<canvas id="ring" width="120" height="120" role="img" aria-label="Ring progres 70 persen, versi canvas">
Ring hijau menunjukkan progres unduhan 70 persen.
</canvas>
<figcaption>Versi canvas: digambar oleh JavaScript ke piksel.</figcaption>
</figure>
<script src="studi-dua-cara.js" defer></script>
</body>
</html>function gambarRing() {
const kanvas = document.querySelector("#ring");
const konteks = kanvas.getContext("2d");
konteks.lineWidth = 12;
konteks.strokeStyle = "#f3f4f6";
konteks.beginPath();
konteks.arc(60, 60, 45, 0, Math.PI * 2);
konteks.stroke();
konteks.strokeStyle = "#1a6b54";
konteks.beginPath();
konteks.arc(60, 60, 45, -Math.PI / 2, Math.PI * 2 * 0.7 - Math.PI / 2);
konteks.stroke();
konteks.fillStyle = "#1f2937";
konteks.font = "bold 20px sans-serif";
konteks.textAlign = "center";
konteks.fillText("70%", 60, 67);
}
gambarRing();Output yang Dihasilkan:
Jendela browser menampilkan dua gambar identik 120x120:
- Ring abu terang penuh
- Busur hijau 70% keliling, mulai dari titik pukul 12 searah jarum jam
- Teks "70%" gelap di tengah ring
- Bagian SVG terdiri atas elemen DOM; bagian canvas berupa pikselMari kita bedah kuncinya:
- Baris 13-14 pada HTML (dua
circle): lingkaran pertama menjadi jalur abu penuh; lingkaran kedua memakaistroke-dasharray="198 283", yaitu busur hijau 198 dari keliling sekitar 283 (2 x pi x 45), tepat 70%. transform="rotate(-90 60 60)": memutar titik awal busur ke atas; tanpa rotasi, busur mulai di pukul 3.- Baris 15 pada HTML (
text): persentase menjadi elemen DOM, terbaca pembaca layar. - Baris 5-9 pada JS (ring abu):
lineWidthdanstrokeStyledisetel, lalu lingkaran penuh distroke; urutannya menggantikan atribut deklaratif milik SVG. - Baris 11-14 pada JS (busur hijau):
arcdigambar dari sudut-Math.PI / 2(titik pukul 12) sejauh 70% dari 2 x pi radian; hitungan trigonometri ini harga yang dibayar immediate mode. - Baris 16-19 pada JS (
fillText): teks persentase dilukis ke piksel dengantextAligntengah.
Bisnis berubah menjadi 85%: versi SVG cukup mengganti stroke-dasharray menjadi “240 283” dan teksnya; versi canvas harus mengosongkan kanvas lalu menggambar ulang dari awal. Perbedaan kerja ini cermin retained mode versus immediate mode.
Peta Lanjutan #
Jalur pendalaman terbuka di tiga arah. Animasi SVG dapat lewat CSS, SMIL (animasi berbasis markup di dalam file), atau JavaScript yang mengubah atribut; pustaka seperti D3 menjadikan SVG basis chart interaktif. Sisi canvas berlanjut ke loop requestAnimationFrame, konteks WebGL untuk grafis tiga dimensi, dan manipulasi piksel lewat getImageData. Materi HTML tinggal satu section lagi: Browser dan Web Platform membahas mesin yang mengerjakan markup ini, dari parsing hingga DOM.
Referensi resmi untuk pendalaman:
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
studi-dua-cara.html
Unduh berkas<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ring Progres: SVG dan Canvas</title>
</head>
<body>
<h1>Progres Unduhan: 70%</h1>
<p>Visual yang sama, digambar dengan dua teknologi berbeda.</p>
<figure>
<svg viewBox="0 0 120 120" width="120" height="120" role="img" aria-label="Ring progres 70 persen, versi SVG">
<circle cx="60" cy="60" r="45" fill="none" stroke="#f3f4f6" stroke-width="12"/>
<circle cx="60" cy="60" r="45" fill="none" stroke="#1a6b54" stroke-width="12" stroke-linecap="round" stroke-dasharray="198 283" transform="rotate(-90 60 60)"/>
<text x="60" y="67" text-anchor="middle" font-size="20" font-weight="bold" fill="#1f2937">70%</text>
</svg>
<figcaption>Versi SVG: dua lingkaran dan satu teks di dalam DOM.</figcaption>
</figure>
<figure>
<canvas id="ring" width="120" height="120" role="img" aria-label="Ring progres 70 persen, versi canvas">
Ring hijau menunjukkan progres unduhan 70 persen.
</canvas>
<figcaption>Versi canvas: digambar oleh JavaScript ke piksel.</figcaption>
</figure>
<script src="studi-dua-cara.js" defer></script>
</body>
</html>
studi-dua-cara.js
Unduh berkasfunction gambarRing() {
const kanvas = document.querySelector("#ring");
const konteks = kanvas.getContext("2d");
konteks.lineWidth = 12;
konteks.strokeStyle = "#f3f4f6";
konteks.beginPath();
konteks.arc(60, 60, 45, 0, Math.PI * 2);
konteks.stroke();
konteks.strokeStyle = "#1a6b54";
konteks.beginPath();
konteks.arc(60, 60, 45, -Math.PI / 2, Math.PI * 2 * 0.7 - Math.PI / 2);
konteks.stroke();
konteks.fillStyle = "#1f2937";
konteks.font = "bold 20px sans-serif";
konteks.textAlign = "center";
konteks.fillText("70%", 60, 67);
}
gambarRing();