每條游來游去的小魚,都是正在瀏覽這一頁的訪客,有一條是你自己 ( ´ ▽ ` )ノ 覺得干擾閱讀的話,可以把小魚關掉。
雨痕
bg冷雨在玻璃上靜靜滑落
| 名稱 | 描述 |
|---|---|
| Canvas Shader | 使用 GLSL 開發,直接在 GPU 上執行,比 Canvas 2D API 更快,但也更難 |
| DOM to Image | 將 DOM 元素轉換為圖片的技術,基於 SVG foreignObject 實現 |
| CSS Anchor Positioning | CSS 新功能,允許元素相對於其他元素(錨點)進行定位 |
| Post-processing | 增強渲染效果,例如:鏡頭模糊、顏色分割等等 |
把任何 DOM 元素(圖片、文字等等)放進 bg-rain-trail 的 slot,就能讓內容多上一層下雨的玻璃。
可以調整水珠密度、尺寸、折射強度與滑落速度。

陌生的冷雨捎來遠方氣漩的涼意又是個美麗的雨天
<template> <div class="w-full flex flex-col gap-4 py-2"> <div class="example-ctrl grid grid-cols-2 gap-4 p-4 lg:grid-cols-4"> <base-input v-model.number="options.dropDensity" type="range" :label="`${t('dropDensity')}: ${options.dropDensity}`" :min="4" :max="30" :step="1" />
<base-input v-model.number="options.dropSize" type="range" :label="`${t('dropSize')}: ${options.dropSize}`" :min="0.5" :max="2" :step="0.01" />
<!-- <base-input v-model.number="options.refraction" type="range" :label="`${t('refraction')}: ${options.refraction}`" :min="0" :max="0.2" :step="0.001" /> -->
<base-input v-model.number="options.fallSpeed" type="range" :label="`${t('fallSpeed')}: ${options.fallSpeed}`" :min="0" :max="1" :step="0.01" />
<base-input v-model.number="options.blurAmount" type="range" :label="`${t('blurAmount')}: ${options.blurAmount}`" :min="0" :max="0.01" :step="0.0001" /> </div>
<bg-rain-trail class="aspect-video w-full overflow-hidden rounded-lg" :drop-density="options.dropDensity" :drop-size="options.dropSize" :refraction="options.refraction" :fall-speed="options.fallSpeed" :blur-amount="options.blurAmount" > <div class="relative h-full w-full"> <img src="/painting-codfish-rain.webp" :alt="t('sceneAlt')" class="h-full w-full rounded-2xl object-cover" >
<div class="absolute inset-0 flex items-end justify-end p-4 text-white" > <div class="text-right text-xs leading-[2] tracking-widest md:text-base"> <span class="block">{{ t('verse1') }}</span> <span class="block">{{ t('verse2') }}</span> </div> </div> </div> </bg-rain-trail> </div></template>
<script setup lang="ts">import { ref } from 'vue'import { useI18n } from 'vue-i18n'import BaseInput from '../../base-input.vue'import BgRainTrail from '../bg-rain-trail.vue'
const { t } = useI18n()
const options = ref({ dropDensity: 30, dropSize: 1.5, refraction: 0.005, fallSpeed: 0.25, blurAmount: 0.0005,})</script>此效果移植自 Martijn Steinrucken (BigWings) 2017 年的 Heartfelt shader (CC BY-NC-SA 3.0)
刪除 HAS_HEART 與 USE_POST_PROCESSING(雷電 / 漸暈 / 心形造型)等示範用裝飾,只保留下雨核心邏輯
canvas 怎麼貼齊 target
Section titled “canvas 怎麼貼齊 target”canvas 透過 <Teleport>
移到 <body> 之下,
再用 CSS Anchor Positioning
把位置與尺寸綁定到 target:
.bg-rain-trail-canvas top: anchor(top) left: anchor(left) width: anchor-size(width) height: anchor-size(height)target 滾動或尺寸變化時,瀏覽器會原生重算 canvas 位置,不經過 JS,所以零延遲。(≖‿ゝ≖)✧
不支援 anchor positioning 的舊瀏覽器會 fallback 到 JS 的 transform: translate(),
會有約一個 frame 的位置延遲(這是 compositor scroll 的物理限制)。(。-`ω´-)
interface Props { /** * CSS selector,指定後雨滴效果會套用到頁面上對應的 DOM,並忽略 slot 內容。 * 若同時提供 selector 與 slot,優先採用 selector。 */ selector?: string; /** 雨珠在畫面上的密度,數值越大水珠越密集。@default 12 */ dropDensity?: number; /** 雨珠尺寸係數,1 為基準大小。@default 1 */ dropSize?: number; /** 折射強度,越高扭曲越明顯。@default 0.01 */ refraction?: number; /** 滑落速度倍率。@default 0.25 */ fallSpeed?: number; /** 玻璃整體霧化程度,0 為清澈、值越大越朦朧。@default 0.0000001 */ blurAmount?: number; /** * canvas 的 z-index * @default 1 */ zIndex?: number; /** * snapdom 擷取倍率(相對 CSS 像素,已含裝置像素比),越低紋理越糊但擷取越快;雨層霧化採樣後通常看不出差異。 * 未指定時用 `min(devicePixelRatio, 2)`。 */ captureScale?: number;}<!-- @slot 玻璃後方的場景內容;指定 `selector` 後此插槽不會渲染 --><slot />Methods
Section titled “Methods”interface Expose { /** 手動觸發重新擷取 DOM 紋理,用於 slot 內容變動或外部 DOM 改變後同步畫面 */ recapture: () => Promise<void>;}