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? O zaman 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, resim dosyası yüklemek için genellikle 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 registerPaint işlevini kullanarak bir boya iş akışı sınıfı kaydedebiliriz:

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> çizmeyi biliyorsanız boyalı iş akışında çizim yapabilirsiniz. geometry, elimizdeki 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ı.

Burada yaygın olarak kullanılan bir arka plan resmi kullanmanın farkı, desenin kullanıcı metin alanını yeniden boyutlandırdığında istek üzerine 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ı kalıbı ama farklı boyutlarda karelere sahip her seferinde yeni bir iş akışı mı yazmak istesek azdır? Yanıtım hayır.

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

Neyse ki, boyama 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ğ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

Yazma sırasında yalnızca Chrome'da boyama iş uygulaması bulunuyordu. Diğer tüm tarayıcı tedarikçilerinden olumlu sinyaller olsa da çok fazla ilerleme kaydedilmedi. Güncel kalmak için Is Houdini yet? (Houdini Henüz Hazır mı?) sayfasını düzenli olarak kontrol edin. Bu süre zarfında, boyama iş akışı için destek olmasa bile kodunuzun çalışmaya devam etmesi için aşamalı geliştirme 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ş parçacığı 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ş akışı desteklenmeyen tarayıcılarda ikinci beyan geçersizdir ve silinir. Bu da ilk bildirimin geçerli olmasını sağlar.

CSS Paint Polyfill

Birçok kullanım için, modern tarayıcılara CSS Özel Boyama ve Boyama İş Akışı desteği ekleyen CSS Boyama Polyfilli'ni de kullanabilirsiniz.

Kullanım alanları

Boyama iş akışları için birçok kullanım alanı vardır. Bu örneklerden bazıları diğerlerinden daha belirgindir. Bunlardan biri, DOM'nizin boyutunu küçültmek için boyama iş akışı kullanmaktır. Öğeler genellikle CSS kullanılarak süsleme oluşturmak için eklenir. Örneğin, Materyal Tasarım Lite'ta dalga efektli düğme, dalganın kendisini 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ştirmek ve parametreleştirmek çok daha kolay olan bir öğeniz vardır.

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.

Bana göre en heyecan verici potansiyel, boyama iş akışının, bir tarayıcıda henüz sahip olmadığı CSS özelliklerinin etkili bir şekilde çoklu doldurulmasına olanak sağlaması. Örneğin, Chrome'a kendiliğinden inene kadar konik gradyanları çoklu dolduracak şekilde uygulayabilirsiniz. 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, bir elmas:

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

mask-image, öğenin boyutunda bir resim alır. Maske resminin şeffaf ve öğenin şeffaf olduğu alanlar. 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. Hemen boyama iş akışı aracının sunduğu yeni imkanları 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.