CSS Paint API'sı

Chrome 65'teki yeni imkanlar

CSS Paint API ("CSS Custom Paint" veya "Houdini'nin boya iş uygulaması" olarak da bilinir) Chrome 65'ten itibaren varsayılan olarak etkindir. Bu nedir? Bununla ne yapabilirsin? İşleyiş şekli Öyleyse okumaya devam edin...

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

Boyama iş uygulaması yazma

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

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

registerPaint('myPainter', MyPainter);

paint() geri çağırması içinde ctx ifadesini, <canvas> sağlayıcısından bildiğimiz CanvasRenderingContext2D ile aynı şekilde kullanabiliriz. <canvas> çizmeyi biliyorsanız boya işçisi yapabilirsiniz. geometry, elimizdeki kanvasın genişliğini ve yüksekliğini bize bildirir. properties Bu makalenin ilerleyen kısımlarında açıklayacağım.

Giriş örneği olarak, dama tahtası boyama işçisi yazalım ve bunu bir <textarea> arka plan resmi olarak kullanalım. (Varsayılan olarak yeniden boyutlandırılabilir olduğundan 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);

Geçmişte <canvas> kullandıysanız bu kod size tanıdık gelecektir. Canlı demoyu buradan izleyin.

Arka plan resmi olarak dama tahtası desenli metin alanı
Arka plan resmi olarak dama tahtası desenli metin alanı.

Burada ortak bir arka plan resmi kullanmanın farkı, kullanıcı metin alanını yeniden boyutlandırdığında kalıbın isteğe bağlı olarak yeniden çizilmesidir. Bu, arka plan resminin, yüksek yoğunluklu ekranlar için gereken ücret de dahil olmak üzere her zaman tam olarak olması gereken büyüklükte olduğu anlamına gelir.

Bu çok iyi bir özellik ama aynı zamanda da çok hareketsiz. Aynı deseni farklı boyutlarda karelere sahip her seferinde yeni bir iş akışı mı yazmak istedik? Yanıtım hayır!

İş akışınızı parametre olarak ayarlama

Neyse ki boya iş akışı, diğer CSS özelliklerine erişebilir. Bu durumda, properties ek parametresi devreye girer. Sınıfa statik bir inputProperties özelliği vererek özel özellikler dahil olmak üzere herhangi bir CSS özelliğinde yapılan değişikliklere abone olabilirsiniz. Değerler size properties parametresiyle 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 aynı kodu farklı dama tahtası türlerinin tamamında kullanabiliriz. Ama daha da iyisi, artık Geliştirici Araçları'na gidip doğru görünümü bulana kadar değerlerle uğraşabiliriz.

Boyama iş uygulamasını desteklemeyen tarayıcılar

Yazıldığı sırada yalnızca Chrome'a boyama iş uygulaması uygulanmaktadır. Diğer tüm tarayıcı tedarikçilerinden olumlu sinyaller olsa da pek bir ilerleme yaşanmamıştır. Son gelişmelerden haberdar olmak için düzenli olarak Houdini Hazır mı? sayfasını kontrol edin. Bu sırada, boya işçisi desteği olmasa bile kodunuzun çalışmaya devam etmesi için progresif geliştirme (pwa) kullandığınızdan emin olun. Her şeyin beklendiği gibi çalıştığından emin olmak için kodunuzu iki yerde düzenlemeniz gerekir: CSS ve JS.

JS'de boya iş uygulaması desteğini algılamak için CSS nesnesini kontrol edebilirsiniz: js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } CSS tarafında iki seçeneğiniz vardır. @supports kullanabilirsiniz:

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

Daha kapsamlı bir yöntem ise CSS'nin, içinde bilinmeyen bir işlev varsa özellik bildiriminin tamamını geçersiz kılıp ardından yoksaydığı gerçeğini kullanmaktır. Bir özelliği iki kez belirtirseniz (önce boya iş uygulaması olmadan ve ardından boya iş parçacığı ile) progresif geliştirme elde edersiniz:

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

Boya iş parçacığını destekleyen tarayıcılarda ikinci background-image bildirimi ilkinin üzerine yazılır. Boyama iş akışı desteği olmayan tarayıcılarda ikinci beyan geçersiz olur ve silinir. İlk açıklama geçerli olur.

CSS Boya Polyfill'i

Birçok kullanım için modern tarayıcılara CSS Özel Boya ve Boyama İşletleri desteğini ekleyen CSS Paint Polyfill'i de kullanmak mümkündür.

Kullanım alanları

Boya iş parçacıklarının birçok kullanım alanı vardır. Bunlardan bazıları diğerlerinden daha barizdir. Bunlardan en bariz olanlardan biri, DOM'nizin boyutunu küçültmek için boya iş uygulamasıdır. Öğeler sadece CSS kullanarak süslemeler oluşturmak için genellikle eklenir. Örneğin, Material Design Lite'ta dalga efektli düğme, dalganın kendisini uygulamak için 2 ek <span> öğesi içerir. Çok sayıda düğmeniz olması, çok sayıda DOM öğesinin eklenmesine neden olabilir ve mobil cihazlarda performansın düşmesine yol açabilir. Bunun yerine dalga efektini boya iş uygulaması kullanarak uygularsanız 0 ek öğe ve yalnızca bir boya iş uygulaması elde edersiniz. Ayrıca, özelleştirilmesi ve parametreleştirilmesi çok daha kolay olan bir özelliğe sahipsiniz.

Boyama iş akışı kullanmanın bir diğer avantajı da (çoğu senaryoda), boya iş akışı kullanan bir çözümün bayt bakımından küçük olmasıdır. Elbette bu dengenin bir farkı vardır: Tuvalin boyutu veya parametrelerden herhangi biri her değiştiğinde boya kodunuz çalışır. Dolayısıyla, kodunuz karmaşıksa ve uzun sürerse jank'ın ortaya çıkmasına neden olabilir. Chrome, uzun süre çalışan boya iş parçacıklarının bile ana iş parçacığının duyarlılığını etkilememesi için boya iş parçacıklarını ana iş parçacığının dışına taşımaya çalışmaktadır.

Bana göre en heyecan verici potansiyel, boyama işinin, CSS özelliklerinin daha verimli bir şekilde çoklu doldurulmasına olanak vermesi. Bu özellik, tarayıcıda henüz bulunmayan bir özellik. Buna örnek olarak, yerel olarak Chrome'a gelene kadar konik renk geçişlerini çoklu doldurmak verilebilir. Başka bir örnek: Bir CSS toplantısında, artık birden fazla kenarlık rengi olabileceğine karar verilmiş. İş arkadaşım Ian Kilpatrick bu yeni CSS davranışı için boya işçisi kullanarak bir çoklu dolgu yazdı.

Kalıpların dışına çıkmak

Çoğu kişi boya iş uygulaması hakkında bilgi edindiğinde arka plan ve kenarlık resimlerini düşünmeye başlar. Boyama iş öğesinin kullanımı daha az kolay bir kullanım alanı, DOM öğelerinin rastgele şekillere sahip olmasını sağlamak için mask-image işlevidir. Örneğin, elmas:

Elmas şeklindeki DOM öğesi.
Elmas şeklindeki DOM öğesi.

mask-image, öğenin boyutunda bir resim çeker. Maske resminin şeffaf, öğenin şeffaf olduğu alanlar. Maske resminin opak, öğenin opak olduğu alanlar.

Şimdi Chrome'da

Boyama iş akışı, bir süredir Chrome Canary'de. Chrome 65'te ise varsayılan olarak etkindir. Haydi, boya iş parçacığının sunduğu yeni olanakları deneyin ve ne yaptığınızı bize gösterin! Daha fazla ilham almak için Vincent De Oliveira'nın koleksiyonuna göz atın.