Files
front/components/AnimatedBackground.vue
T

106 lines
2.6 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)
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
}, [offscreen])
}
function safeReloadShader() {
reloadShader()
}
function reloadShader() {
const bounds = canvas.value?.getBoundingClientRect()
if (!bounds) { return }
worker.postMessage({
command: 'reloadShader',
quality: settingsStore.shaderQuality,
framerate: settingsStore.shaderFramerate,
bounds: { left: bounds.left, bottom: bounds.bottom },
screen: { height: window.screen.height, width: window.screen.width, devicePixelRatio },
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
colorStart: props.colorStart,
colorEnd: props.colorEnd
})
}
function resizeShader() {
const bounds = canvas.value?.getBoundingClientRect()
if (!bounds) { return }
worker.postMessage({
command: 'changeBounds',
bounds: { left: bounds.left, bottom: bounds.bottom },
screen: { height: window.screen.height, width: window.screen.width, devicePixelRatio },
colorStart: props.colorStart,
colorEnd: props.colorEnd
})
}
function endShader() {
worker.postMessage({
command: 'killShader'
})
}
watch(() => [settingsStore.shaderQuality, settingsStore.shaderFramerate], () => {
safeReloadShader()
})
let has_resized = false
watch(() => [props.colorEnd, props.colorStart], () => {
if (!has_resized) {
has_resized = true
nextTick(() => {
resizeShader()
has_resized = false
})
}
})
onMounted(async () => {
nextTick(() => {
initShader()
window.addEventListener("resize", resizeShader, true)
safeReloadShader()
})
})
onUnmounted(() => {
window.removeEventListener("resize", resizeShader)
endShader()
})
</script>
<template>
<canvas v-if="settingsStore.shaderQuality != 0" ref="canvas" id="background">test</canvas>
</template>
<style scoped>
#background {
left: 0;
position: absolute;
height: 100%;
width: 100%;
}
</style>