CSS Paint API

Kemungkinan baru di Chrome 65

CSS Paint API (juga dikenal sebagai "CSS Custom Paint" atau "Houdini’s paint worklet") adalah diaktifkan secara default mulai Chrome 65. Apa ini? Yang dapat Anda lakukan data tersebut? Dan bagaimana cara kerjanya? Yah, silakan baca terus, sampai jumpa...

CSS Paint API memungkinkan Anda membuat gambar secara terprogram setiap kali CSS mengharapkan gambar. Properti seperti background-image atau border-image biasanya digunakan dengan url() untuk memuat file gambar atau dengan CSS bawaan fungsi seperti linear-gradient(). Alih-alih menggunakannya, Anda sekarang dapat menggunakan paint(myPainter) untuk mereferensikan worklet cat.

Menulis worklet cat

Untuk menentukan worklet cat yang disebut myPainter, kita perlu memuat cat CSS file worklet menggunakan CSS.paintWorklet.addModule('my-paint-worklet.js'). Di sana 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 ketika kita CanvasRenderingContext2D seperti yang kita ketahui dari <canvas>. Jika Anda mengetahui cara menggambar <canvas>, Anda dapat menggambar di worklet cat. geometry memberi tahu kita lebar dan tinggi kanvas yang kita butuhkan. properties Saya akan akan dijelaskan nanti dalam artikel ini.

Sebagai contoh pengantar, mari kita tulis worklet cat checkerboard dan menggunakannya sebagai gambar latar <textarea>. (Saya menggunakan area teks 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 seharusnya tidak asing. Lihat live demo di sini.

Textarea dengan pola kotak-kotak sebagai gambar latar
Textarea dengan pola kotak-kotak sebagai gambar latar.

Perbedaan dari penggunaan gambar latar umum di sini adalah bahwa pola akan digambar ulang sesuai permintaan, setiap kali pengguna mengubah ukuran textarea. Artinya gambar latar harus selalu sebesar yang diperlukan, termasuk kompensasi untuk layar dengan kepadatan tinggi.

Cukup bagus, tetapi juga cukup statis. Apakah kita ingin menulis worklet setiap kali kami menginginkan pola yang sama tetapi dengan ukuran yang berbeda persegi? Jawabannya adalah tidak.

Memparameterisasi worklet

Untungnya, worklet cat dapat mengakses properti CSS lainnya, di mana parameter tambahan properties ikut berperan. Dengan memberikan class statis inputProperties, Anda dapat berlangganan untuk menerima perubahan pada properti CSS, termasuk properti khusus. 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. Tapi bahkan lebih baik, sekarang kita bisa masuk ke DevTools dan mengenali nilai-nilai sampai kami menemukan tampilan yang tepat.

Browser yang tidak mendukung worklet paint

Pada saat penulisan ini, hanya Chrome yang telah mengimplementasikan worklet cat. Selama berada di sana adalah sinyal positif dari semua vendor {i>browser<i} lainnya, tidak ada banyak kemajuan. Untuk mendapatkan info terbaru, lihat Apakah Houdini Sudah Siap? secara rutin. Sementara itu, pastikan untuk menggunakan tambahan agar kode Anda tetap berjalan meskipun tidak ada dukungan untuk paint {i>worklet<i}. Untuk memastikan semuanya bekerja 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 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 cat, lalu dengan — Anda akan mendapatkan {i>progressive enhancement<i}:

textarea {
  background-image: linear-gradient(0, red, blue);
  background-image: paint(myGradient, red, blue);
}

Di browser dengan dukungan untuk worklet paint, deklarasi kedua dari background-image akan menimpa yang pertama. Di browser tanpa dukungan untuk worklet paint, deklarasi kedua tidak valid dan akan dibuang, membiarkan deklarasi pertama berlaku.

Polyfill Cat CSS

Untuk banyak penggunaan, dimungkinkan juga untuk menggunakan Polyfill CSS Paint, yang menambahkan dukungan Worklet Paint dan Paint Kustom CSS ke browser modern.

Kasus penggunaan

Ada banyak kasus penggunaan untuk worklet cat, beberapa di antaranya lebih jelas daripada lainnya. Salah satu yang lebih jelas adalah menggunakan pekerjaan cat untuk mengurangi ukuran DOM Anda. Sering kali, elemen ditambahkan hanya untuk membuat hiasan menggunakan CSS. Misalnya, di Material Design Lite tombol dengan efek ripple berisi 2 elemen <span> tambahan untuk mengimplementasikan riak itu sendiri. Jika Anda memiliki banyak tombol, ini dapat menghasilkan cukup banyak elemen DOM dan dapat menyebabkan penurunan performa di perangkat seluler. Jika Anda menerapkan efek riak menggunakan worklet cat sebagai gantinya, Anda mendapatkan 0 elemen tambahan dan hanya satu worklet cat. Selain itu, Anda memiliki sesuatu yang jauh lebih mudah untuk disesuaikan dan menjadi parameter.

Keuntungan lain dari menggunakan worklet cat adalah — di sebagian besar skenario — sebuah solusi menggunakan worklet paint kecil dalam hal byte. Tentu saja, ada kompromi: kode cat Anda akan berjalan setiap kali ukuran kanvas atau salah satu perubahan parameter. Jadi, jika kode Anda kompleks dan memakan waktu lama, mungkin jank. Chrome sedang berupaya memindahkan worklet cat dari thread utama agar bahkan pekerjaan cat yang berjalan lama pun tidak memengaruhi responsivitas .

Bagi saya, prospek yang paling menarik adalah bahwa pekerjaan cat memungkinkan proses yang efisien polyfill fitur CSS yang belum dimiliki browser. Salah satu contohnya adalah ke polyfill gradien kerucut hingga aplikasi tersebut ditempatkan di Chrome secara native. Contoh lain: di pertemuan CSS, memutuskan bahwa Anda sekarang dapat memiliki beberapa warna {i>border<i}. Saat rapat ini masih berlangsung, rekan saya Ian Kilpatrick menulis polyfill untuk CSS baru ini perilaku model menggunakan worklet cat.

Berpikir kreatif

Kebanyakan orang mulai memikirkan gambar latar dan gambar batas saat mereka pelajari tentang worklet cat. Satu kasus penggunaan yang tidak terlalu intuitif untuk worklet cat adalah mask-image untuk membuat elemen DOM memiliki bentuk arbitrer. Misalnya, belah ketupat:

Elemen DOM berbentuk berlian.
Elemen DOM berbentuk berlian.

mask-image mengambil gambar yang merupakan ukuran elemen. Area tempat gambar mask transparan, elemennya transparan. Area dengan mask gambar buram, elemen tidak tembus pandang.

Sekarang di Chrome

Paint telah ada di Chrome Canary selama beberapa waktu. Dengan Chrome 65, diaktifkan secara default. Silakan coba berbagai kemungkinan baru balok cat itu akan terbuka dan menunjukkan apa yang telah Anda buat. Untuk inspirasi lainnya, lihat koleksi Vincent De Oliveira.