Kemungkinan baru di Chrome 65
CSS Paint API (juga dikenal sebagai “CSS Custom Paint” atau “Houdini's paint worklet”) diaktifkan secara default mulai Chrome 65. Apa ini? Apa yang dapat Anda lakukan dengannya? Dan bagaimana cara kerjanya? Yah, silakan baca terus, apakah kalian akan...
CSS Paint API memungkinkan Anda membuat gambar secara terprogram setiap kali properti CSS mengharapkan gambar. Properti seperti background-image
atau border-image
biasanya digunakan dengan url()
untuk memuat file gambar atau dengan fungsi bawaan CSS
seperti linear-gradient()
. Sebagai gantinya, Anda kini dapat menggunakan
paint(myPainter)
untuk mereferensikan worklet cat.
Menulis worklet cat
Untuk menentukan worklet cat yang disebut myPainter
, kita perlu memuat file worklet
cat CSS menggunakan CSS.paintWorklet.addModule('my-paint-worklet.js')
. Dalam file
tersebut, kita dapat menggunakan fungsi registerPaint
untuk mendaftarkan class worklet cat:
class MyPainter {
paint(ctx, geometry, properties) {
// ...
}
}
registerPaint('myPainter', MyPainter);
Di dalam callback paint()
, kita dapat menggunakan ctx
dengan cara yang sama seperti
CanvasRenderingContext2D
seperti yang kita ketahui dari <canvas>
. Jika Anda tahu cara
menggambar di <canvas>
, Anda dapat menggambar di worklet cat. geometry
memberi tahu kita lebar dan tinggi kanvas yang tersedia. properties
Saya akan
menjelaskannya nanti dalam artikel ini.
Sebagai contoh pengantar, mari kita tulis worklet cat kotak-kotak dan menggunakannya
sebagai gambar latar belakang <textarea>
. (Saya menggunakan textarea karena dapat
diubah ukurannya secara default.):
<!-- index.html -->
<!doctype html>
<style>
textarea {
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
paint(ctx, geom, properties) {
// Use `ctx` as if it was a normal canvas
const colors = ['red', 'green', 'blue'];
const size = 32;
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
const color = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.fillStyle = color;
ctx.rect(x * size, y * size, size, size);
ctx.fill();
}
}
}
}
// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);
Jika Anda pernah menggunakan <canvas>
sebelumnya, kode ini akan terlihat tidak asing. Lihat
demo
langsung
di sini.
Perbedaannya dengan menggunakan gambar latar umum di sini adalah pola akan digambar ulang sesuai permintaan, setiap kali pengguna mengubah ukuran textarea. Artinya, gambar latar selalu sama persis dengan ukuran yang diperlukan, termasuk kompensasi untuk layar dengan kepadatan tinggi.
Hal ini cukup keren, tetapi juga cukup statis. Apakah kita ingin menulis worklet baru setiap kali kita menginginkan pola yang sama, tetapi dengan kotak berukuran berbeda? Jawabannya adalah tidak.
Membuat parameter worklet
Untungnya, worklet cat dapat mengakses properti CSS lainnya, yang merupakan tempat
parameter tambahan properties
digunakan. Dengan memberi class atribut inputProperties
statis, Anda dapat berlangganan perubahan pada properti CSS apa pun, termasuk properti kustom. Nilai akan diberikan kepada Anda melalui
parameter properties
.
<!-- index.html -->
<!doctype html>
<style>
textarea {
/* The paint worklet subscribes to changes of these custom properties. */
--checkerboard-spacing: 10;
--checkerboard-size: 32;
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
// inputProperties returns a list of CSS properties that this paint function gets access to
static get inputProperties() { return ['--checkerboard-spacing', '--checkerboard-size']; }
paint(ctx, geom, properties) {
// Paint worklet uses CSS Typed OM to model the input values.
// As of now, they are mostly wrappers around strings,
// but will be augmented to hold more accessible data over time.
const size = parseInt(properties.get('--checkerboard-size').toString());
const spacing = parseInt(properties.get('--checkerboard-spacing').toString());
const colors = ['red', 'green', 'blue'];
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
ctx.fillStyle = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.rect(x*(size + spacing), y*(size + spacing), size, size);
ctx.fill();
}
}
}
}
registerPaint('checkerboard', CheckerboardPainter);
Sekarang kita dapat menggunakan kode yang sama untuk semua jenis papan catur. Namun, yang lebih bagus lagi, sekarang kita bisa masuk ke DevTools dan mengenali nilai-nilai sampai menemukan tampilan yang tepat.
Browser yang tidak mendukung worklet cat
Pada saat penulisan, hanya Chrome yang telah menerapkan worklet cat. Meskipun ada sinyal positif dari semua vendor browser lainnya, tidak ada banyak progres. Untuk terus mendapatkan informasi terbaru, periksa Sudahkah Houdini Siap? secara berkala. Sementara itu, pastikan untuk menggunakan peningkatan progresif agar kode Anda tetap berjalan meskipun tidak ada dukungan untuk worklet cat. Untuk memastikan semuanya berfungsi seperti yang diharapkan, Anda harus menyesuaikan kode di dua tempat: CSS dan JS.
Mendeteksi dukungan untuk worklet cat di JS dapat dilakukan dengan memeriksa objek CSS
:
js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('mystuff.js');
}
Untuk sisi CSS, Anda memiliki dua opsi. Anda dapat menggunakan @supports
:
@supports (background: paint(id)) {
/* ... */
}
Trik yang lebih ringkas adalah menggunakan fakta bahwa CSS membatalkan dan kemudian mengabaikan seluruh deklarasi properti jika ada fungsi yang tidak diketahui di dalamnya. Jika menentukan properti dua kali — pertama tanpa worklet cat, lalu dengan worklet cat — Anda akan mendapatkan peningkatan progresif:
textarea {
background-image: linear-gradient(0, red, blue);
background-image: paint(myGradient, red, blue);
}
Di browser dengan dukungan untuk worklet paint, deklarasi kedua background-image
akan menimpa deklarasi pertama. Di browser tanpa dukungan
untuk worklet paint, deklarasi kedua tidak valid dan akan dihapus,
sehingga deklarasi pertama tetap berlaku.
Polyfill Cat CSS
Untuk banyak penggunaan, Anda juga dapat menggunakan CSS Paint Polyfill, yang menambahkan dukungan CSS Custom Paint dan Paint Worklet ke browser modern.
Kasus penggunaan
Ada banyak kasus penggunaan untuk worklet cat, beberapa di antaranya lebih jelas daripada
yang lain. Salah satu yang lebih jelas adalah menggunakan paint worklet untuk mengurangi ukuran DOM Anda. Sering kali, elemen ditambahkan semata-mata untuk membuat hiasan
menggunakan CSS. Misalnya, di Material Design Lite, tombol
dengan efek ripple berisi 2 elemen <span>
tambahan untuk menerapkan
ripple itu sendiri. Jika Anda memiliki banyak tombol, hal ini dapat menambah cukup banyak elemen DOM dan dapat menyebabkan penurunan performa di perangkat seluler. Jika Anda
menerapkan efek ripple menggunakan worklet cat,
Anda akan mendapatkan 0 elemen tambahan dan hanya satu worklet cat.
Selain itu, Anda memiliki sesuatu yang jauh lebih mudah disesuaikan dan
diparameterkan.
Keuntungan lain dari penggunaan worklet cat adalah — dalam sebagian besar skenario — solusi yang menggunakan worklet cat berukuran kecil dalam hal byte. Tentu saja, ada konsekuensinya: kode cat Anda akan dijalankan setiap kali ukuran kanvas atau parameter apa pun berubah. Jadi, jika kode Anda kompleks dan memerlukan waktu lama, kode tersebut dapat menyebabkan jank. Chrome sedang berupaya memindahkan worklet cat dari thread utama sehingga worklet cat yang berjalan lama pun tidak memengaruhi responsivitas thread utama.
Bagi saya, prospek yang paling menarik adalah worklet paint memungkinkan polyfill fitur CSS yang efisien yang belum dimiliki browser. Salah satu contohnya adalah mem-polyfill gradien kerucut hingga gradien tersebut muncul di Chrome secara native. Contoh lain: dalam rapat CSS, diputuskan bahwa Anda kini dapat memiliki beberapa warna batas. Saat rapat ini masih berlangsung, kolega saya Ian Kilpatrick menulis polyfill untuk perilaku CSS baru ini menggunakan worklet cat.
Berpikir di luar “kotak”
Kebanyakan orang mulai memikirkan gambar latar dan gambar batas saat mereka
mempelajari worklet cat. Satu kasus penggunaan yang kurang intuitif untuk worklet paint adalah
mask-image
untuk membuat elemen DOM memiliki bentuk arbitrer. Misalnya
diamond:
mask-image
mengambil gambar yang berukuran sama dengan elemen. Area tempat
gambar mask transparan, elemen akan transparan. Area tempat gambar mask
buram, elemen buram.
Sekarang di Chrome
Worklet cat telah ada di Chrome Canary untuk sementara waktu. Dengan Chrome 65, fitur ini diaktifkan secara default. Silakan coba kemungkinan baru yang dibuka oleh worklet cat dan tunjukkan kepada kami apa yang Anda buat. Untuk mendapatkan inspirasi lainnya, lihat koleksi Vincent De Oliveira.