Safari 16.4から、Web Workersを使用したOffscreenCanvas(Context2Dのみ)に対応したため、早速使ってみました。しかし、画像の表示方法がわからず結構苦戦したので、メモとして残します。
OffscreenCanvasとは
Web Workersを使用して、メインスレッドをブロックすることなく、バックグラウンドでCanvasの描画処理を実行可能にする仕組みのことです。
OffscreenCanvasを使用することで、時間のかかる処理を別のスレッドに移すことができるため、UIを担当するメインスレッドの処理を中断・遅延させずにWebページの操作性を向上させ、滑らかなユーザーエクスペリエンスを提供することができます。
サンプルコード
// main script
const canvas = document.getElementById('canvas');
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker('worker.js');
worker.postMessage({ canvas: offscreen }, [ offscreen ]);
// worker script
class WorkerMain {
constructor(canvas) {
this.context = canvas.getContext('2d');
}
async render(src){
const response = await fetch(src);
const blob = await response.blob();
const imageBitmap = await createImageBitmap(blob);
this.context.drawImage(imageBitmap, 0, 0);
}
}
onmessage = async (event) => {
const src = './image.jpg';
const offscreen = event.data.canvas;
const workerMain = new WorkerMain(offscreen);
await workerMain.render(src);
};
説明
fetch()メソッドを使用して画像を取得し、response.blob()メソッドでBlobオブジェクトに変換しています。
const response = await fetch(src);
const blob = await response.blob();
createImageBitmap()メソッドを使用して、BlobオブジェクトからImageBitmapオブジェクトを作成し、Canvasに描画しています。なお、createImageBitmap()メソッドはPromiseを返します。
const imageBitmap = await createImageBitmap(blob);
this.context.drawImage(imageBitmap, 0, 0);
最後に
ワーカー内から直接DOMを扱えないため最初は戸惑いましたが、同じ状況の方の一助となれば幸いです。内容に誤り等ございましたらコメントよろしくお願いします。