Ao combinar OffscreenCanvas com Web Worker, é possível processar imagens sem bloquear a thread principal.
Tecnologias usadas
- Web Worker
- Offscreen Canvas
- Blob
- Bitmap
Interface
export interface WorkerRequestBody { buffer: ArrayBuffer; type: string; size: { height: number; width: number; };}
export interface WorkerResponseBody { buffer: ArrayBuffer; contentType: string;}Processando uma imagem dentro de um Web Worker
async function imageProcessing( data: WorkerRequestBody): Promise<WorkerResponseBody> { const { buffer, type, size } = data;
// Converter o ArrayBuffer de volta em Blob const blob = new Blob([buffer], { type });
// Criar um OffscreenCanvas const canvas = new OffscreenCanvas(size.width, size.height);
// Criar um Bitmap a partir do Blob const bitmap = await createImageBitmap(blob);
// Obter um CanvasRenderingContext2D const ctx = canvas.getContext("2d"); if (!ctx) throw new Error("Context2D is not defined");
// Desenhar a imagem no canvas ctx.drawImage(bitmap, 0, 0);
// Converter para WebP const webp = await canvas.convertToBlob({ type: "image/webp", quality: 0.85, });
// Converter o Blob WebP em ArrayBuffer const buf = await webp.arrayBuffer();
return { buffer: buf, contentType: "image/webp", };}
self.addEventListener("message", async (e: MessageEvent<WorkerRequestBody>) => { const output = await imageProcessing(e.data); // Passar o segundo argumento para transferir a posse do ArrayBuffer para a thread de UI self.postMessage(output, [output.buffer]);});Enviando a imagem para o worker e recebendo o resultado convertido
import MyWorker from "./worker.ts";
const worker = new MyWorker();
const fileInput = document.querySelector<HTMLInputElement>("#js-file-input");
worker.addEventListener("message", (e: MessageEvent<WorkerResponseBody>) => { const { buffer, contentType } = e.data; const blob = new Blob([buffer], { type: contentType });
// do something});
fileInput.addEventListener("change", async (e) => { const [file] = Array.from(fileInput.files); if (!file) return;
const buffer = await file.arrayBuffer(); const type = file.type; const size = { height: 1080, width: 1980 }; // obter o tamanho da imagem
// Enviar para o Web Worker e transferir a posse worker.postMessage( { buffer, type, size }, [buffer] );});Pontos principais
- OffscreenCanvas: uma API de Canvas que funciona dentro de Web Workers
- Transferência de ArrayBuffer: passagem eficiente de dados com transferência de posse
- convertToBlob: conversão para formatos como WebP usando OffscreenCanvas
Resumo
Combinando OffscreenCanvas e Web Worker, é possível executar processamento de imagem sem bloquear a thread principal.
Quando há muitas imagens ou conversões pesadas para processar, essa abordagem mantém a UI responsiva e melhora a experiência do usuário.
hsb.horse