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 dalam menerapkan fitur baru di Canvas2D untuk mengimbangi 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 banyak fitur yang paling banyak diminta:
Persegi panjang bulat
Persegi panjang membulat: fondasi internet, komputasi, bahkan peradaban.
Baik serius, persegi panjang bersudut tumpul sangat berguna: seperti tombol, balon chat, thumbnail, balon ucapan, dan banyak lagi. 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 yang sederhana dan sederhana:
Dengan API baru, ada metode roundRect()
.
ctx.roundRect(upper, left, width, height, borderRadius);
Jadi hal di atas bisa 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 sedikit fungsi lucu untuk menggambar pola retro:
draw90sPattern();
Bagus! Setelah saya selesai dengan pola itu, saya ingin membersihkan 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);
Huh… itu 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? Lalu, kenapa warnanya merah muda? Baiklah, mari kita periksa StackOverflow.
canvas.width = canvas.width;
Mengapa hal ini sangat konyol? Mengapa hal ini sangat sulit?
Tidak lagi. Dengan API baru ini, kami memiliki hal inovatif yang sederhana, elegan, dan indah:
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 harus 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 sepenuhnya dapat dilakukan.
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 },
]);
Semudah itu! Coba dan mainkan parameter dalam demo di sini.
Bagian 3: peningkatan performa
Dengan New Canvas2D API, kami juga ingin meningkatkan performa jika memungkinkan. Kami menambahkan beberapa fitur untuk memberi developer kontrol yang lebih mendetail atas situs mereka dan memungkinkan kecepatan frame yang paling keren:
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. 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 beberapa bencana lain menimpa 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.