1
1
mirror of https://github.com/kokonect-link/cherrypick synced 2025-01-19 00:03:19 +09:00

blurhashを描画するためのcanvasは再利用する

This commit is contained in:
tamaina 2023-06-06 05:47:40 +00:00
parent 8ccf954065
commit 3d4a3d117d
2 changed files with 34 additions and 22 deletions

View File

@ -22,10 +22,10 @@ import TestWebGL2 from '@/workers/test-webgl2?worker';
import { WorkerMultiDispatch } from '@/scripts/worker-multi-dispatch';
import { extractAvgColorFromBlurhash } from '@/scripts/extract-avg-color-from-blurhash';
const workerPromise = new Promise<WorkerMultiDispatch | null>(resolve => {
const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resolve => {
// Web Worker
if (import.meta.env.MODE === 'test') {
resolve(null);
resolve(document.createElement('canvas'));
return;
}
const testWorker = new TestWebGL2();
@ -38,7 +38,10 @@ const workerPromise = new Promise<WorkerMultiDispatch | null>(resolve => {
resolve(workers);
if (_DEV_) console.log('WebGL2 in worker is supported!');
} else {
resolve(null);
const canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
resolve(canvas);
if (_DEV_) console.log('WebGL2 in worker is not supported...');
}
testWorker.terminate();
@ -70,6 +73,7 @@ const props = withDefaults(defineProps<{
width?: number;
cover?: boolean;
forceBlurhash?: boolean;
onlyAvgColor?: boolean; // Blurhash使
}>(), {
transition: null,
src: null,
@ -79,6 +83,7 @@ const props = withDefaults(defineProps<{
width: 64,
cover: true,
forceBlurhash: false,
onlyAvgColor: false,
});
const viewId = uuid();
@ -139,8 +144,8 @@ function drawImage(bitmap: CanvasImageSource) {
ctx.drawImage(bitmap, 0, 0, canvasWidth, canvasHeight);
}
async function draw() {
if (!canvas.value || props.hash == null) return;
function drawAvg() {
if (!canvas.value || !props.hash) return;
const ctx = canvas.value.getContext('2d');
if (!ctx) return;
@ -149,25 +154,28 @@ async function draw() {
ctx.beginPath();
ctx.fillStyle = extractAvgColorFromBlurhash(props.hash) ?? '#888';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
}
const workers = await workerPromise;
if (workers) {
workers.postMessage(
async function draw() {
if (props.hash == null) return;
drawAvg();
if (props.onlyAvgColor) return;
const work = await canvasPromise;
if (work instanceof WorkerMultiDispatch) {
work.postMessage(
{
id: viewId,
hash: props.hash,
width: canvasWidth,
height: canvasHeight,
},
undefined,
);
} else {
try {
const work = document.createElement('canvas');
work.width = canvasWidth;
work.height = canvasHeight;
render(props.hash, work);
ctx.drawImage(work, 0, 0, canvasWidth, canvasHeight);
drawImage(work);
} catch (error) {
console.error('Error occured during drawing blurhash', error);
}
@ -179,9 +187,9 @@ function workerOnMessage(event: MessageEvent) {
drawImage(event.data.bitmap as ImageBitmap);
}
workerPromise.then(worker => {
if (worker) {
worker.addListener(workerOnMessage);
canvasPromise.then(work => {
if (work instanceof WorkerMultiDispatch) {
work.addListener(workerOnMessage);
}
draw();
@ -204,8 +212,10 @@ onMounted(() => {
});
onUnmounted(() => {
workerPromise.then(worker => {
worker?.removeListener(workerOnMessage);
canvasPromise.then(work => {
if (work instanceof WorkerMultiDispatch) {
work?.removeListener(workerOnMessage);
}
});
});
</script>

View File

@ -1,5 +1,7 @@
import { render } from 'buraha';
const canvas = new OffscreenCanvas(64, 64);
onmessage = (event) => {
// console.log(event.data);
if (!('id' in event.data && typeof event.data.id === 'string')) {
@ -8,8 +10,8 @@ onmessage = (event) => {
if (!('hash' in event.data && typeof event.data.hash === 'string')) {
return;
}
const work = new OffscreenCanvas(event.data.width ?? 64, event.data.height ?? 64);
render(event.data.hash, work);
const bitmap = work.transferToImageBitmap();
render(event.data.hash, canvas);
const bitmap = canvas.transferToImageBitmap();
postMessage({ id: event.data.id, bitmap });
};