CSS Paint API'sı

Chrome 65'teki yeni olanaklar

CSS Paint API ("CSS Özel Boya" veya "Houdini'nin boya işleyicisi" olarak da bilinir), Chrome 65'ten itibaren varsayılan olarak etkindir. Bu nedir? Ne işe yarar? Nasıl çalışıyor? Peki, okumaya devam edin.

CSS Paint API, bir CSS mülkü resim beklediğinde programatik olarak resim oluşturmanıza olanak tanır. background-image veya border-image gibi özellikler genellikle bir resim dosyası yüklemek için url() ile veya linear-gradient() gibi yerleşik CSS işlevleriyle kullanılır. Bunları kullanmak yerine artık boya iş parçacığına referans vermek için paint(myPainter) kullanabilirsiniz.

Boya çalışma sayfası yazma

myPainter adlı bir boyama işleyicisi tanımlamak için CSS.paintWorklet.addModule('my-paint-worklet.js') kullanarak bir CSS boyama işleyicisi dosyası yüklememiz gerekir. Bu dosyada, bir boyama iş parçası sınıfını kaydetmek için registerPaint işlevini kullanabiliriz:

class MyPainter {
  paint(ctx, geometry, properties) {
    // ...
  }
}

registerPaint('myPainter', MyPainter);

paint() geri çağırma işlevinde, ctx'u <canvas>'dan bildiğimiz CanvasRenderingContext2D gibi kullanabiliriz. <canvas>'te nasıl çizim yapacağınızı biliyorsanız boyama iş parçasında da çizim yapabilirsiniz. geometry, kullanabileceğimiz kanvasın genişliğini ve yüksekliğini belirtir. properties Bu konuyu makalenin ilerleyen bölümlerinde açıklayacağım.

Giriş örneği olarak bir dama tahtası boyama iş aleti yazıp bunu bir <textarea>'ün arka plan resmi olarak kullanalım. (Varsayılan olarak yeniden boyutlandırılabildiği için bir metin alanı kullanıyorum.):

<!-- 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);

<canvas>'ü daha önce kullandıysanız bu kod size tanıdık gelecektir. Canlı demoyu buradan izleyebilirsiniz.

Arka plan resmi olarak dama tahtası deseni içeren metin alanı
Arka plan resmi olarak dama tahtası desenli metin alanı.

Buradaki yaygın arka plan resmiyle arasındaki fark, kullanıcı metin alanını yeniden boyutlandırdığında desenin isteğe bağlı olarak yeniden çizilmesidir. Bu, yüksek yoğunluklu ekranlar için telafi dahil olmak üzere arka plan resminin her zaman tam olarak olması gerektiği kadar büyük olduğu anlamına gelir.

Bu oldukça etkileyici ancak aynı zamanda oldukça statik. Aynı deseni farklı boyutlarda karelerle kullanmak istediğimizde her seferinde yeni bir çalışma sayfası yazmak ister miyiz? Yanıtımız hayır.

Çalışma alanınızı parametreleştirme

Neyse ki boyama iş parçası diğer CSS mülklerine erişebilir. Bu noktada ek parametre properties devreye girer. Sınıfa statik bir inputProperties özelliği ekleyerek özel özellikler dahil olmak üzere herhangi bir CSS özelliğindeki değişikliklere abone olabilirsiniz. Değerler size properties parametresi aracılığıyla verilir.

<!-- 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);

Artık farklı türdeki tüm dama tahtaları için aynı kodu kullanabiliriz. Daha da iyisi, artık DevTools'a gidip doğru görünümü bulana kadar değerlerle oynayabiliriz.

Boyama iş parçacığını desteklemeyen tarayıcılar

Bu makale hazırlanırken boyama iş parçası yalnızca Chrome'da uygulanıyordu. Diğer tüm tarayıcı tedarikçilerinden olumlu sinyaller olsa da çok fazla ilerleme kaydedilmedi. Gelişmeleri takip etmek için Houdini Hazır mı? başlıklı makaleyi düzenli olarak inceleyin. Bu süre zarfında, paintworklet desteği olmasa bile kodunuzun çalışmaya devam etmesini sağlamak için aşamalı geliştirmeyi kullandığınızdan emin olun. İşlemlerin beklendiği gibi çalışmasını sağlamak için kodunuzu iki yerde ayarlamanız gerekir: CSS ve JS.

JS'de boyama iş aracının desteğini CSS nesnesi kontrol ederek tespit edebilirsiniz: js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } CSS tarafında iki seçeneğiniz vardır. @supports'ü şu amaçlarla kullanabilirsiniz:

@supports (background: paint(id)) {
  /* ... */
}

Daha kompakt bir hile, CSS'nin içinde bilinmeyen bir işlev varsa özellik bildiriminin tamamını geçersiz kılması ve ardından yoksayması gerçeğini kullanmaktır. Bir mülkü iki kez belirtirseniz (önce boya iş parçası olmadan, sonra boya iş parçasıyla) aşamalı iyileştirme elde edersiniz:

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

Boyama iş parçacığı desteği olan tarayıcılarda, background-image için ikinci bildirim ilk bildirimin üzerine yazar. Boyama iş öğesi için destek bulunmayan tarayıcılarda ikinci beyan geçersizdir ve atılır. Böylece ilk beyan geçerli kalır.

CSS Paint Polyfill

Birçok kullanım için, modern tarayıcılara CSS Özel Boya ve Boya Worklet'i desteği ekleyen CSS Paint Polyfill'i de kullanabilirsiniz.

Kullanım alanları

Boyama iş parçacıklarının birçok kullanım alanı vardır. Bazıları diğerlerinden daha belirgindir. En belirgin olanlardan biri, DOM'unuzun boyutunu azaltmak için paint iş parçacığı kullanmaktır. Öğeler genellikle CSS kullanılarak süsleme oluşturmak için eklenir. Örneğin, Material Design Lite'ta dalga efekti içeren düğme, dalga efektini uygulamak için 2 ek <span> öğesi içerir. Çok sayıda düğmeniz varsa bu, çok sayıda DOM öğesi oluşturabilir ve mobil cihazlarda performansın düşmesine neden olabilir. Bunun yerine dalga efektini boya iş parçacığı kullanarak uygularsanız 0 ek öğe ve yalnızca bir boya iş parçacığı elde edersiniz. Ayrıca, özelleştirmesi ve parametre eklemesi çok daha kolay bir öğeye sahip olursunuz.

Boyama iş parçacığının bir diğer avantajı, çoğu senaryoda boyama iş parçacığının kullanıldığı çözümlerin bayt açısından küçük olmasıdır. Elbette bunun bir dezavantajı vardır: Boyama kodunuz, kanvasın boyutu veya parametrelerden herhangi biri değiştiğinde çalışır. Bu nedenle, kodunuz karmaşıksa ve uzun süre alıyorsa gecikmeye neden olabilir. Chrome, uzun süre çalışan boyama iş parçacıklarının bile ana iş parçacığının duyarlılığını etkilememesi için boyama iş parçacıklarını ana iş parçacığının dışına taşıma üzerinde çalışıyor.

Benim için en heyecan verici gelişme, boyama iş parçacığının, tarayıcıda henüz bulunmayan CSS özelliklerinin verimli bir şekilde doldurulmasına olanak tanımasıdır. Örneğin, konik gradyanlar Chrome'a doğal olarak gelene kadar bunları polimorfik hale getirmek için kullanabilirsiniz. Başka bir örnek: Bir CSS toplantısında, artık birden fazla kenar rengi kullanabileceğinize karar verildi. Bu toplantı devam ederken iş arkadaşım Ian Kilpatrick, paint iş parçacığı kullanarak bu yeni CSS davranışı için bir polyfill yazdı.

"Kalıpların" dışına çıkma

Çoğu kullanıcı, boyama iş aleti hakkında bilgi edindiğinde arka plan resimleri ve kenar resimleri hakkında düşünmeye başlar. Boyama iş aleti için daha az sezgisel bir kullanım alanı, DOM öğelerinin rastgele şekillere sahip olmasını sağlamaktır.mask-image Örneğin, elmas:

Elmas şeklinde bir DOM öğesi.
Elmas şeklinde bir DOM öğesi.

mask-image, öğenin boyutunda bir resim alır. Maske resminin şeffaf olduğu alanlar, öğe de şeffaf olur. Maske resminin opak olduğu alanlar, öğe opak.

Artık Chrome'da

Boyama iş aleti bir süredir Chrome Canary'da bulunuyor. Chrome 65'te bu özellik varsayılan olarak etkindir. Boyama iş akışı aracının sunduğu yeni olasılıkları deneyin ve oluşturduklarınızı bize gösterin. Daha fazla ilham almak için Vincent De Oliveira'nın koleksiyonuna göz atın.