Snow bg
A snowy background effect for your webpage -- it even accumulates snow! ( ´ ▽ ` )ノ
Usage Examples
Basic Usage
Use the v-bg-static directive to make designated elements accumulate snow.
You can also adjust the snowflake image and size.
View example source code
<template>
<div class="w-full flex items-center justify-center py-10">
<div class="grid grid-cols-4 gap-10">
<base-checkbox
v-model="enable"
v-bg-static
:label="t('startSnow')"
class="col-span-3 border border-gray-200 rounded-full p-4 px-6"
/>
<base-btn
v-bg-static
:label="t('sweep')"
class="border-gray-200 !rounded-full"
@click="sweep()"
/>
<base-input
:label="t('snowflakeImage')"
class="col-span-2"
>
<div
v-bg-static
class="border rounded"
>
<input
type="file"
accept="image/*"
class="px-2 py-1"
@change="handleImageChange"
>
</div>
</base-input>
<base-input
v-model="options.size"
:label="`${t('particleSize')}: ${options.size}`"
type="range"
:min="1"
:max="20"
class="col-span-2"
/>
</div>
<bg-snow
ref="bgRef"
class="fixed left-0 top-0 z-[100] h-full w-full"
:class="{ 'opacity-0': !enable }"
:image-src="imgUrl"
:size="options.size"
/>
</div>
</template>
<script setup lang="ts">
import { useObjectUrl } from '@vueuse/core'
import { useData } from 'vitepress'
import { onUnmounted, ref, useTemplateRef, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseBtn from '../../base-btn.vue'
import BaseCheckbox from '../../base-checkbox.vue'
import BaseInput from '../../base-input.vue'
import BgSnow from '../bg-snow.vue'
import { vBgStatic } from '../v-bg-static'
const { t } = useI18n()
const enable = ref(false)
const imgFile = ref<File>()
function handleImageChange(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0]
imgFile.value = file
}
const imgUrl = useObjectUrl(imgFile)
const bgRef = useTemplateRef('bgRef')
const options = ref({
size: 8,
})
function sweep() {
bgRef.value?.sweep()
}
const { isDark } = useData()
const oriValue = isDark.value
watch(enable, (value) => {
isDark.value = value
})
onUnmounted(() => {
isDark.value = oriValue
})
</script>How It Works
The snow animation is based on Babylon.js's particle system. The snow accumulation effect performs collision detection on DOM elements marked with v-bg-static.
Here's a small challenge: since the number of snowflakes can be very large, the computational cost can be quite significant. If we calculate directly on the main thread, the page would become laggy and janky.
This is where a neat trick comes in: Offscreen Canvas! ( •̀ ω •́ )✧
This technology allows the entire Canvas rendering to be handed off to a Web Worker. This means all computations, including the expensive calculation tasks, no longer run on the main thread, so you don't have to worry about UI jank. (/≧▽≦)/
So, what about browser support? ლ(´ 口`ლ)
As of 2024/12/22, browser support is at 95.21%, so it should be safe to use. ᕕ( ゚ ∀。)ᕗ
When you look at the source code, you might notice I used a package called Comlink. This package greatly simplifies the way messages are passed between Web Workers and the main thread. ( ´ ▽ ` )ノ
Otherwise, using postMessage to pass messages is really cumbersome. ⎝(・ω´・⎝)
Source Code
API
Methods
defineExpose({
/** 清除積雪 */
sweep,
})