Files
front/components/AnimatedBackground.vue
T

112 lines
2.7 KiB
Vue

<script setup lang="ts">
const settingsStore = useSettingsStore()
import ShaderWorker from '~/assets/workers/ShaderWorker?worker'
const worker = new ShaderWorker()
const canvas = ref<HTMLCanvasElement | null>(null)
const canvas_resize_temp = ref<HTMLCanvasElement | null>(null)
export interface Props {
colorStart?: [number, number, number]
colorEnd?: [number, number, number]
}
const props = withDefaults(defineProps<Props>(), {
colorStart: () => [0, .3, 0],
colorEnd: () => [0, 1, 0]
})
function initShader() {
if (!canvas.value) { return }
const offscreen = canvas.value?.transferControlToOffscreen()
worker.postMessage({
command: "initShader",
canvas: offscreen,
screen: { height: window.innerHeight * devicePixelRatio, width: window.innerWidth * devicePixelRatio, devicePixelRatio },
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
}, [offscreen])
if (settingsStore.shaderFramerate == 0) {
killShader()
}
resizeShader()
}
function recolorShader() {
worker.postMessage({
command: 'recolorShader',
colorStart: props.colorStart,
colorEnd: props.colorEnd
})
}
function resizeShader() {
worker.postMessage({
command: 'resizeShader',
screen: { height: window.innerHeight * devicePixelRatio, width: window.innerWidth * devicePixelRatio, devicePixelRatio },
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
})
}
function killShader() {
worker.postMessage({
command: 'killShader'
})
}
function resumeShader() {
worker.postMessage({
command: 'resumeShader',
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
})
}
watch(() => [settingsStore.shaderFramerate], () => {
if (settingsStore.shaderFramerate == 0) {
killShader()
return
}
resumeShader()
})
watch(() => [settingsStore.shaderQuality], () => {
resizeShader()
})
watch(() => [props.colorEnd, props.colorStart], () => {
recolorShader()
})
onMounted(async () => {
nextTick(() => {
recolorShader()
initShader()
window.addEventListener("resize", resizeShader, true)
})
})
onUnmounted(() => {
window.removeEventListener("resize", resizeShader)
killShader()
})
</script>
<template>
<canvas ref="canvas" id="background" :class="{ pixelated: settingsStore.shaderPixelated }" width="480"
height="270">test</canvas>
</template>
<style scoped>
#background {
left: 0;
position: absolute;
height: 100%;
width: 100%;
image-rendering: smooth;
}
#background.pixelated {
image-rendering: crisp-edges;
}
</style>