Durch die Kombination von OffscreenCanvas und Web Worker lässt sich Bildverarbeitung umsetzen, ohne den Main Thread zu blockieren.
Verwendete Technologien
- 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;}Ein Bild im Web Worker verarbeiten
async function imageProcessing( data: WorkerRequestBody): Promise<WorkerResponseBody> { const { buffer, type, size } = data;
// ArrayBuffer zurück in ein Blob umwandeln const blob = new Blob([buffer], { type });
// OffscreenCanvas erzeugen const canvas = new OffscreenCanvas(size.width, size.height);
// Aus dem Blob ein Bitmap erzeugen const bitmap = await createImageBitmap(blob);
// CanvasRenderingContext2D holen const ctx = canvas.getContext("2d"); if (!ctx) throw new Error("Context2D is not defined");
// Bild auf das Canvas zeichnen ctx.drawImage(bitmap, 0, 0);
// In WebP umwandeln const webp = await canvas.convertToBlob({ type: "image/webp", quality: 0.85, });
// WebP-Blob in ArrayBuffer umwandeln const buf = await webp.arrayBuffer();
return { buffer: buf, contentType: "image/webp", };}
self.addEventListener("message", async (e: MessageEvent<WorkerRequestBody>) => { const output = await imageProcessing(e.data); // Zweites Argument angeben, um den Besitz des ArrayBuffer an den UI-Thread zu übertragen self.postMessage(output, [output.buffer]);});Ein Bild an den Worker senden und das konvertierte Bild empfangen
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 }; // Bildgröße ermitteln
// An den Web Worker senden und Besitz übertragen worker.postMessage( { buffer, type, size }, [buffer] );});Wichtige Punkte
- OffscreenCanvas: eine Canvas-API, die im Web Worker verwendet werden kann
- ArrayBuffer-Transfer: Daten werden effizient übergeben, indem der Besitz übertragen wird
- convertToBlob: mit OffscreenCanvas in Formate wie WebP konvertieren
Zusammenfassung
Mit OffscreenCanvas und Web Worker lässt sich Bildverarbeitung ausführen, ohne den Main Thread zu blockieren.
Wenn viele Bilder verarbeitet oder teure Konvertierungen ausgeführt werden müssen, bleibt die UI reaktionsfähig und die Nutzererfahrung verbessert sich.
hsb.horse