En combinant OffscreenCanvas et Web Worker, on peut traiter des images sans bloquer le thread principal.
Technologies utilisées
- 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;}Traiter une image dans un Web Worker
async function imageProcessing( data: WorkerRequestBody): Promise<WorkerResponseBody> { const { buffer, type, size } = data;
// Reconvertir l'ArrayBuffer en Blob const blob = new Blob([buffer], { type });
// Créer un OffscreenCanvas const canvas = new OffscreenCanvas(size.width, size.height);
// Créer un Bitmap à partir du Blob const bitmap = await createImageBitmap(blob);
// Récupérer un CanvasRenderingContext2D const ctx = canvas.getContext("2d"); if (!ctx) throw new Error("Context2D is not defined");
// Dessiner l'image sur le canvas ctx.drawImage(bitmap, 0, 0);
// Convertir en WebP const webp = await canvas.convertToBlob({ type: "image/webp", quality: 0.85, });
// Convertir le Blob WebP en 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); // Fournir le deuxième argument pour transférer la propriété de l'ArrayBuffer au thread UI self.postMessage(output, [output.buffer]);});Passer une image au worker et récupérer l’image convertie
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 }; // récupérer la taille de l'image
// Envoyer au Web Worker et transférer la propriété worker.postMessage( { buffer, type, size }, [buffer] );});Points importants
- OffscreenCanvas : une API Canvas utilisable dans un Web Worker
- Transfert d’ArrayBuffer : on passe les données efficacement en transférant la propriété
- convertToBlob : permet de convertir vers WebP et d’autres formats via OffscreenCanvas
Résumé
En combinant OffscreenCanvas et Web Worker, on peut exécuter un traitement d’image sans bloquer le thread principal.
Quand il faut traiter beaucoup d’images ou exécuter des conversions coûteuses, cette approche conserve la réactivité de l’interface et améliore l’expérience utilisateur.
hsb.horse