Di dunia shader, mesh, dan filter, Canvas2D mungkin tidak membuat Anda tertarik. Namun, seharusnya tidak demikian.
30–40% halaman web memiliki elemen <canvas>
dan 98% dari semua kanvas menggunakan konteks rendering
Canvas2D. Ada Canvas2D di mobil, di kulkas,
dan di luar angkasa (benar-benar).
Memang, API ini sedikit ketinggalan zaman dalam hal gambar 2D canggih. Untungnya, kami telah bekerja keras menerapkan fitur baru di Canvas2D untuk mengejar CSS, menyederhanakan ergonomi, dan meningkatkan performa.
Bagian 1: memahami CSS
CSS memiliki beberapa perintah gambar yang sangat tidak ada di Canvas2D. Dengan API baru, kami telah menambahkan beberapa fitur yang paling banyak diminta:
Persegi panjang bulat
Persegi panjang membulat: fondasi internet, komputasi, bahkan peradaban.
Sejujurnya, persegi panjang membulat sangat berguna: sebagai tombol, balon chat, thumbnail, balon ucapan, dan sebagainya. Anda selalu dapat membuat persegi panjang membulat di Canvas2D, tetapi sedikit berantakan:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'magenta';
const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;
ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();
Semua ini diperlukan untuk persegi panjang membulat sederhana dan sederhana:
Dengan API baru, ada metode roundRect()
.
ctx.roundRect(upper, left, width, height, borderRadius);
Jadi, kode di atas dapat sepenuhnya diganti dengan:
ctx.roundRect(10, 10, 200, 100, 20);
Metode ctx.roundRect()
juga menggunakan array untuk argumen borderRadius
hingga empat
angka. Radius ini mengontrol empat sudut persegi panjang membulat dengan cara yang sama
seperti untuk CSS. Contoh:
ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);
Gradien Konikal
Anda telah melihat gradien linear:
const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);
Gradien radial:
const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');
ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
Namun, bagaimana dengan gradien kerucut yang bagus?
const grad = ctx.createConicGradient(0, 100, 100);
grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);
Pengubah teks
Kemampuan rendering teks Canvas2D sangat tertinggal. Chrome telah menambahkan beberapa atribut baru ke rendering teks Canvas2D:
- ctx.letterSpacing
- ctx.wordSpacing
- ctx.fontVariant
- ctx.fontKerning
- ctx.fontStretch
- ctx.textDecoration
- ctx.textUnderlinePosition
- ctx.textRendering
Semua atribut ini cocok dengan pasangan CSS-nya dengan nama yang sama.
Bagian 2: penyesuaian ergonomis
Sebelumnya, beberapa hal dengan Canvas2D dapat dilakukan, tetapi tidak perlu rumit untuk diterapkan. Berikut beberapa peningkatan kualitas hidup untuk developer JavaScript yang ingin menggunakan Canvas2D:
Reset konteks
Untuk menjelaskan cara menghapus kanvas, saya telah menulis fungsi kecil yang lucu untuk menggambar pola retro:
draw90sPattern();
Bagus! Setelah selesai dengan pola tersebut, saya ingin menghapus kanvas dan menggambar sesuatu yang lain.
Tunggu, bagaimana cara menghapus kanvas lagi? Oh, iya! ctx.clearRect()
, tentu saja.
ctx.clearRect(0, 0, canvas.width, canvas.height);
Hmm… tidak berhasil. Oh, iya! Saya harus mereset transformasi terlebih dahulu:
ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);

Sempurna! Kanvas kosong yang bagus. Sekarang, mari kita mulai menggambar garis horizontal yang bagus:
ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();
Grrrr! Jawaban Anda salah. 😡 Apa fungsi baris tambahan tersebut? Selain itu, mengapa warnanya merah muda? Baik, mari kita periksa StackOverflow.
canvas.width = canvas.width;
Mengapa hal ini sangat konyol? Mengapa hal ini sangat sulit?
Tidak lagi. Dengan API baru, kami memiliki fitur yang sederhana, elegan, dan menarik:
ctx.reset();
Maaf, prosesnya memerlukan waktu lama.
Filter
Filter SVG adalah dunia tersendiri. Jika Anda baru mengenalnya, sebaiknya baca The Art Of SVG Filters And Why It Is Awesome, yang menunjukkan beberapa potensinya yang luar biasa.
Filter gaya SVG sudah tersedia untuk Canvas2D. Anda hanya perlu bersedia meneruskan filter sebagai URL yang mengarah ke elemen filter SVG lain di halaman:
<svg>
<defs>
<filter id="svgFilter">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
<feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
<feColorMatrix type="hueRotate" values="90" />
</filter>
</defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);
Hal ini cukup mengacaukan pola kita:
Namun, bagaimana jika Anda ingin melakukan hal di atas, tetapi tetap dalam JavaScript dan tidak perlu repot dengan string? Dengan API baru, hal ini sangat mungkin.
ctx.filter = new CanvasFilter([
{ filter: 'gaussianBlur', stdDeviation: 5 },
{
filter: 'convolveMatrix',
kernelMatrix: [
[-3, 0, 0],
[0, 0.5, 0],
[0, 0, 3],
],
},
{ filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);
Sangat mudah. Coba dan mainkan parameter dalam demo di sini.
Bagian 3: peningkatan performa
Dengan Canvas2D API Baru, kami juga ingin meningkatkan performa jika memungkinkan. Kami menambahkan beberapa fitur untuk memberi developer kontrol yang lebih terperinci atas situs mereka dan memungkinkan kecepatan frame yang paling lancar:
Akan sering dibaca
Gunakan getImageData()
untuk membaca data piksel kembali dari kanvas. Proses ini bisa sangat lambat. API baru ini memberi
Anda cara untuk menandai kanvas secara eksplisit untuk dibaca kembali (misalnya, untuk efek generatif).
Hal ini memungkinkan Anda mengoptimalkan berbagai hal di balik layar dan menjaga kanvas tetap cepat untuk berbagai kasus
penggunaan yang lebih besar. Fitur ini telah ada di Firefox selama beberapa waktu dan akhirnya kami menjadikannya bagian dari spesifikasi
kanvas.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
Hilangnya konteks
Mari kita buat tab yang sedih menjadi bahagia lagi. Jika klien kehabisan memori GPU atau bencana lain terjadi pada kanvas, Anda kini dapat menerima callback dan menggambar ulang sesuai kebutuhan:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);
Jika Anda ingin membaca lebih lanjut tentang konteks dan kehilangan kanvas, WHATWG memiliki penjelasan yang bagus di wiki-nya.
Kesimpulan
Baik Anda baru menggunakan Canvas2D, sudah menggunakannya selama bertahun-tahun, atau telah menghindari penggunaannya selama bertahun-tahun, kami ingin menyarankan Anda untuk melihat kembali canvas. Ini adalah API-next-door yang sudah ada selama ini.