Kemungkinan baru di Chrome 65
CSS Paint API (juga dikenal sebagai “CSS Custom Paint” atau “Worklet cat Houdini”) diaktifkan secara default mulai dari Chrome 65. Fitur apa ini? Apa yang dapat Anda lakukan? Dan bagaimana cara kerjanya? Nah, teruslah membaca, bisakah Anda’...
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 ganti menggunakannya, Anda kini dapat menggunakan
paint(myPainter)
untuk mereferensikan worklet paint.
Menulis worklet cat
Untuk menentukan worklet paint yang disebut myPainter
, kita perlu memuat file worklet paint CSS
menggunakan CSS.paintWorklet.addModule('my-paint-worklet.js')
. Dalam file tersebut, kita dapat menggunakan fungsi registerPaint
untuk mendaftarkan class worklet paint:
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 tahu cara
menggambar di <canvas>
, Anda dapat menggambar di worklet paint. geometry
memberi tahu kita
lebar dan tinggi kanvas yang dapat digunakan. properties
akan saya jelaskan nanti dalam artikel ini.
Sebagai contoh pengantar, mari kita tulis worklet cat kotak-kotak dan gunakan
sebagai gambar latar <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>
, kode ini akan terlihat tidak asing. Lihat
demo
langsung di sini.
Perbedaan dengan menggunakan gambar latar belakang umum di sini adalah pola akan digambar ulang sesuai permintaan, setiap kali pengguna mengubah ukuran textarea. Artinya, gambar latar selalu berukuran sama persis dengan yang diperlukan, termasuk kompensasi untuk layar berkepadatan tinggi.
Cukup keren, tapi juga cukup statis. Apakah kita ingin menulis worklet baru setiap kali kita menginginkan pola yang sama tetapi dengan ukuran kotak yang berbeda? Jawabannya adalah tidak.
Membuat parameter {i>worklet<i} Anda
Untungnya, worklet paint dapat mengakses properti CSS lainnya, di mana parameter tambahan properties
dapat berperan. Dengan memberi class atribut
inputProperties
statis tersebut, Anda dapat berlangganan untuk mengetahui 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 yang berbeda. Tetapi yang lebih bagus lagi, kita sekarang bisa masuk ke DevTools dan mengotak-atik nilai sampai kita menemukan tampilan yang tepat.
Browser yang tidak mendukung worklet paint
Pada saat penulisan, hanya Chrome yang menerapkan worklet paint. Meskipun ada sinyal positif dari semua vendor browser lainnya, tidak ada banyak progres. Untuk mendapatkan informasi terbaru, periksa Apakah Houdini Sudah Siap? secara rutin. 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 paint 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 dengan menggunakan fakta bahwa CSS membatalkan validasi dan kemudian mengabaikan seluruh deklarasi properti jika ada fungsi yang tidak diketahui di dalamnya. Jika Anda menentukan properti dua kali — pertama tanpa worklet paint, lalu dengan worklet paint — Anda akan mendapatkan progressive enhancement:
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 yang pertama. Di browser tanpa dukungan
untuk worklet paint, deklarasi kedua tidak valid dan akan dihapus,
sehingga deklarasi pertama tetap berlaku.
Polyfill Paint CSS
Untuk banyak penggunaan, Anda juga dapat menggunakan CSS Paint Polyfill, yang menambahkan dukungan CSS Custom Paint dan Paint Worklets 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 worklet paint untuk mengurangi ukuran
DOM Anda. Sering kali, elemen ditambahkan hanya untuk membuat hiasan
menggunakan CSS. Misalnya, dalam Material Design Lite, tombol
dengan efek ripple berisi 2 elemen <span>
tambahan untuk menerapkan
ripple itu sendiri. Jika Anda memiliki banyak tombol, tindakan ini dapat menambahkan hingga cukup banyak
elemen DOM dan dapat menyebabkan penurunan performa di perangkat seluler. Jika Anda
menerapkan efek ripple menggunakan worklet paint, Anda akan mendapatkan 0 elemen tambahan dan hanya satu worklet paint.
Selain itu, Anda memiliki sesuatu yang jauh lebih mudah untuk disesuaikan dan
diparameterisasi.
Keunggulan lain dari penggunaan worklet paint adalah bahwa — dalam sebagian besar skenario — solusi yang menggunakan worklet paint berukuran kecil dalam hal byte. Tentu saja, ada konsekuensinya: kode paint Anda akan berjalan setiap kali ukuran kanvas atau salah satu parameter berubah. Jadi, jika kode Anda rumit dan memakan waktu lama, kode tersebut dapat menyebabkan jank. Chrome sedang berupaya memindahkan worklet paint dari thread utama sehingga worklet paint 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 gradien kerucut polyfill hingga mendarat di Chrome secara native. Contoh lain: dalam rapat CSS, diputuskan bahwa Anda kini dapat memiliki beberapa warna batas. Sementara rapat ini masih berlangsung, rekan saya Ian Kilpatrick menulis polyfill untuk perilaku CSS baru ini menggunakan worklet paint.
Berpikir di luar kebiasaan
Kebanyakan orang mulai memikirkan gambar latar dan gambar bingkai saat
mempelajari {i>worklet<i} 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 merupakan ukuran elemen. Area tempat
gambar mask transparan, elemennya juga transparan. Area tempat gambar
mask buram, elemen buram.
Kini di Chrome
Worklet cat telah ada di Chrome Canary selama beberapa waktu. Pada Chrome 65, fitur ini diaktifkan secara default. Lanjutkan dan cobalah kemungkinan-kemungkinan baru yang terbuka dari {i>worklet<i} cat dan tunjukkan kepada kami apa yang Anda bangun! Untuk mendapatkan inspirasi lainnya, lihat koleksi Vincent De Oliveira.