diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index ca912fabf5..a0e7ee30bc 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -22,8 +22,13 @@ import TestWebGL2 from '@/workers/test-webgl2?worker'; const workerPromise = new Promise(resolve => { const testWorker = new TestWebGL2(); testWorker.addEventListener('message', event => { - if (event.data.result) resolve(new DrawBlurhash()); - else resolve(null); + if (event.data.result) { + console.log('WebGL2 is supported in worker.') + resolve(new DrawBlurhash()); + } else { + console.log('WebGL2 is not supported in worker.') + resolve(null); + } testWorker.terminate(); }); }); @@ -74,6 +79,7 @@ let canvasWidth = $ref(64); let canvasHeight = $ref(64); let imgWidth = $ref(props.width); let imgHeight = $ref(props.height); +let bitmapTmp = $ref(); const hide = computed(() => !loaded || props.forceBlurhash); function waitForDecode() { @@ -108,19 +114,43 @@ watch([() => props.width, () => props.height, root], () => { immediate: true, }); -async function draw(transfer: boolean = false) { +workerPromise.then(worker => { + if (!worker) return; + + worker.postMessage({ + id: viewId, + hash: props.hash, + }); + + worker.addEventListener('message', event => { + if (event.data.id !== viewId) return; + drawImage(event.data.bitmap as ImageBitmap); + }); +}); + +function drawImage(bitmap: CanvasImageSource) { + // canvasがない(mountedされていない)場合はTmpに保存しておく + if (!canvas.value) { + bitmapTmp = bitmap; + return; + } + + bitmapTmp = undefined; + + // canvasがあったらすぐに描画する + const ctx = canvas.value.getContext('2d'); + if (!ctx) return; + ctx.drawImage(bitmap, 0, 0, canvasWidth, canvasHeight); +} + +async function draw() { if (!canvas.value || props.hash == null) return; const worker = await workerPromise; if (worker) { - let offscreen: OffscreenCanvas | undefined; - if (transfer) { - offscreen = canvas.value.transferControlToOffscreen(); - } worker.postMessage({ id: viewId, - canvas: offscreen ?? undefined, hash: props.hash, - }, offscreen ? [offscreen] : []); + }); } else { try { const work = document.createElement('canvas'); @@ -128,8 +158,7 @@ async function draw(transfer: boolean = false) { work.height = canvasHeight; render(props.hash, work); const bitmap = await createImageBitmap(work); - const ctx = canvas.value.getContext('2d'); - ctx?.drawImage(bitmap, 0, 0, canvasWidth, canvasHeight); + drawImage(bitmap); } catch (error) { console.error('Error occured during drawing blurhash', error); } @@ -145,8 +174,10 @@ watch(() => props.hash, () => { }); onMounted(() => { - draw(true); - waitForDecode(); + // drawImageがmountedより先に呼ばれている場合はここで描画する + if (bitmapTmp) { + drawImage(bitmapTmp); + } }); onUnmounted(() => { diff --git a/packages/frontend/src/workers/draw-blurhash.ts b/packages/frontend/src/workers/draw-blurhash.ts index 3a19c63cc0..f5bb7f9716 100644 --- a/packages/frontend/src/workers/draw-blurhash.ts +++ b/packages/frontend/src/workers/draw-blurhash.ts @@ -1,30 +1,15 @@ import { render } from 'buraha'; -const canvases = new Map(); - onmessage = async (event) => { // console.log(event.data); if (!('id' in event.data && typeof event.data.id === 'string')) { return; } - if (event.data.delete) { - canvases.delete(event.data.id); - return; - } - if (event.data.canvas) { - canvases.set(event.data.id, event.data.canvas); - } if (!('hash' in event.data && typeof event.data.hash === 'string')) { return; } - const canvas = event.data.canvas ?? canvases.get(event.data.id); - if (!canvas) { - throw new Error('No canvas'); - } const work = new OffscreenCanvas(canvas.width, canvas.height); render(event.data.hash, work); const bitmap = await createImageBitmap(work); - const ctx = canvas.getContext('2d'); - ctx?.drawImage(bitmap, 0, 0, canvas.width, canvas.height); - postMessage({ result: true }); + postMessage({ id: event.data.id, bitmap }); };