OffscreenCanvas: Bir web çalışanıyla tuval işlemlerinizi hızlandırın

Tim Dresser

Canvas, ekranda her türlü grafik çizmenin popüler bir yoludur ve WebGL dünyasına giriş noktasıdır. Şekil, resim çizmek, animasyon çalıştırmak veya hatta video içeriği görüntülemek ve işlemek için kullanılabilir. Bu teknoloji, genellikle medya açısından zengin web uygulamalarında ve online oyunlarda güzel kullanıcı deneyimleri oluşturmak için kullanılır.

Komut dosyası yazılabilir. Yani kanvas üzerine çizilen içerik, programatik olarak (ör. JavaScript'te) oluşturulabilir. Bu sayede kanvas büyük bir esneklik sunar.

Aynı zamanda, modern web sitelerinde komut dosyası yürütme, kullanıcı yanıt vermeme sorunlarının en yaygın kaynaklarından biridir. Tuval mantığı ve oluşturma işlemi, kullanıcı etkileşimiyle aynı iş parçacığında gerçekleştiği için animasyonlarla ilgili (bazen ağır olan) hesaplamalar, uygulamanın gerçek ve algılanan performansına zarar verebilir.

Neyse ki OffscreenCanvas bu tehdide karşı bir yanıttır.

Tarayıcı desteği

  • Chrome: 69.
  • Edge: 79.
  • Firefox: 105.
  • Safari: 16.4.

Kaynak

Daha önce, tuval çizim özellikleri <canvas> öğesine bağlıydı. Bu da doğrudan DOM'ye bağlı olduğu anlamına geliyordu. OffscreenCanvas, adından da anlaşılacağı gibi DOM'u ekrandan uzaklaştırarak DOM ile Canvas API'yi birbirinden ayırır.

Bu ayırma sayesinde, OffscreenCanvas'ın oluşturulması DOM'dan tamamen ayrılır ve bu nedenle, ikisi arasında senkronizasyon olmadığından normal kanvasla karşılaştırıldığında bazı hız iyileştirmeleri sunar.

Daha da önemlisi, DOM mevcut olmasa bile bir Web İşleyici'de kullanılabilir. Bu sayede her türlü ilgi çekici kullanım alanı mümkün olur.

OffscreenCanvas'ı bir çalışanda kullanma

İşçiler, web'de iş parçacıklarının sürümüdür. Arka planda görev çalıştırmanıza olanak tanır.

Komut dosyalarınızın bir kısmını bir çalışana taşımak, uygulamanıza ana iş parçacığında kullanıcı açısından kritik görevleri gerçekleştirmek için daha fazla alan sağlar. OffscreenCanvas olmadan, DOM olmadığından Canvas API'yi bir çalışanda kullanmak mümkün değildi.

OffscreenCanvas, DOM'a bağlı olmadığından kullanılabilir. Aşağıdaki örnekte, bir çalışanda degrade rengi hesaplamak için OffscreenCanvas kullanılmaktadır:

// file: worker.js
function getGradientColor(percent) {
  const canvas = new OffscreenCanvas(100, 1);
  const ctx = canvas.getContext('2d');
  const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  gradient.addColorStop(0, 'red');
  gradient.addColorStop(1, 'blue');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, ctx.canvas.width, 1);
  const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
  const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
  return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}

getGradientColor(40);  // rgba(152, 0, 104, 255 )

Ana ileti dizisinin engellemesini kaldırma

Ağır hesaplamaları bir çalışana taşımak, ana iş parçacığında önemli miktarda kaynak boşaltmanıza olanak tanır. Normal kanvası bir OffscreenCanvas örneğine yansıtmak için transferControlToOffscreen yöntemini kullanın. OffscreenCanvas'a uygulanan işlemler, kaynak kanvasta otomatik olarak oluşturulur.

const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);

Aşağıdaki örnekte, yoğun hesaplama renk teması değişirken gerçekleşir. Bu işlem, hızlı bir masaüstünde bile birkaç milisaniye sürer. Animasyonları ana iş parçacığında veya çalışanda çalıştırmayı seçebilirsiniz. Ana mesaj dizisinde, yoğun görev çalışırken düğmeyle etkileşimde bulunamazsınız. Mesaj dizisi engellenir. İşçi söz konusu olduğunda kullanıcı arayüzü duyarlılığı etkilenmez.

Demo

Bu durum tersi yönde de geçerlidir: Meşgul olan ana iş parçacığı, bir işleyicide çalışan animasyonu etkilemez. Aşağıdaki demoda gösterildiği gibi, görsel takılmaları önlemek ve ana iş parçacığı trafiğine rağmen sorunsuz bir animasyon sağlamak için bu özelliği kullanabilirsiniz.

Demo

Normal bir kanvasta, ana iş parçacığı yapay olarak aşırı yüklendiğinde animasyon durur. İşleyici tabanlı OffscreenCanvas ise sorunsuz bir şekilde oynatılır.

OffscreenCanvas API genellikle normal Canvas Öğesi ile uyumlu olduğundan, bunu aşamalı bir geliştirme olarak ve piyasadaki önde gelen grafik kitaplıklarından bazılarıyla da kullanabilirsiniz.

Örneğin, özelliği algılayabilir ve varsa oluşturucuda tuval seçeneğini belirterek Three.js ile kullanabilirsiniz:

const canvasEl = document.querySelector('canvas');
const canvas =
  'OffscreenCanvas' in window
    ? canvasEl.transferControlToOffscreen()
    : canvasEl;
canvas.style = {width: 0, height: 0};
const renderer = new THREE.WebGLRenderer({canvas: canvas});

Buradaki tek sorun, Three.js'in kanvasın style.width ve style.height özelliğine sahip olmasını beklemesidir. OffscreenCanvas, DOM'dan tamamen ayrılmış olduğu için bu özelliği içermez. Bu nedenle, bu özelliği ya stub'layarak ya da bu değerleri orijinal kanvas boyutlarına bağlayan mantık sağlayarak kendiniz sağlamanız gerekir.

Aşağıda, bir çalışanda temel bir Three.js animasyonunun nasıl çalıştırılacağı gösterilmektedir:

Demo

DOM ile ilgili API'lerden bazılarının bir çalışanda kullanılamadığını unutmayın. Bu nedenle, dokular gibi daha gelişmiş Three.js özelliklerini kullanmak istiyorsanız daha fazla geçici çözüme ihtiyacınız olabilir. Bu özellikleri nasıl denemeye başlayacağınızla ilgili fikir edinmek için Google I/O 2017'deki videoya göz atın.

Tuvalin grafik özelliklerini yoğun şekilde kullanıyorsanız OffscreenCanvas, uygulamanızın performansını olumlu yönde etkileyebilir. Tuval oluşturma bağlamlarını işçilere sunmak, web uygulamalarındaki paralelliği artırır ve çok çekirdekli sistemlerin daha iyi kullanılmasını sağlar.

Ek kaynaklar