头像
YIBI

正在加载...

网站天气特效系统的实现

2026-06-15VueCanvasCSS动效组件

概述

WeatherEffect 是一个全屏天气特效组件,使用 Canvas 渲染粒子飘落 + CSS 呼吸灯光球,支持春夏秋冬四季切换,以及关闭状态。


四季效果

🌸 春季 — 樱花飘落

  • Canvas 粉色椭圆花瓣,旋转飘落(0.6-1.2 px/帧)
  • 50 个粒子同时渲染
  • 5 个粉金暖色 CSS 光球,filter: blur(40px) 模糊扩散
  • 淡粉色径向光晕滤镜 + 暖黄阳光感
  • 光球 7 秒循环呼吸(透明度 0.04⇌0.18,缩放 0.9⇌1.15)

☔ 夏季 — 夏雨倾盆

  • Canvas 蓝色雨丝,高速垂落(10-14 px/帧)
  • 150 个粒子同时渲染
  • 4 个蓝青冷色 CSS 光球
  • 深蓝暗色遮罩滤镜

🍂 秋季 — 落叶纷飞

  • Canvas 橙棕椭圆叶片,左右摇摆(摇摆幅度 2px/帧)
  • 5 种随机颜色(#d97706 ~ #dc2626)
  • 50 个粒子同时渲染
  • 5 个琥珀暖色 CSS 光球
  • 棕色叠加 + 琥珀波光滤镜

❄️ 冬季 — 雪花飘落

  • Canvas 白色圆形雪点,慢速摇摆(0.3-0.6 px/帧)
  • 70 个粒子同时渲染
  • 5 个白紫冷色 CSS 光球
  • 白色明朗滤镜

组件接口

vue
<WeatherEffect :season="season" />
Prop 说明
season 'spring' 春季
season 'summer' 夏季
season 'autumn' 秋季
season 'winter' 冬季
season 'none' 关闭

集成方式

组件放在全局布局 layouts/default.vue 中,用 <ClientOnly> 包裹(Canvas 不兼容 SSR):

vue
<ClientOnly>
  <WeatherEffect :season="season" />
</ClientOnly>

季节状态通过模块级共享 ref 在布局和页面间同步:

ts
// composables/useWeather.ts
const _season = ref('none')
export function useWeatherSeason() { return _season }

首页的天气选择卡片调用 useWeatherSeason() 获取同一个 ref,点击切换即同步到全局布局。


技术要点

层面 技术
粒子渲染 Canvas 2D + requestAnimationFrame
光球渲染 CSS div + radial-gradient + filter: blur(40px)
呼吸动画 @keyframes orb-breathe 7s ease-in-out infinite alternate
滤镜遮罩 background: radial-gradient(...) 内联样式
遮罩层级 z-index: 15 + pointer-events: none(穿透点击)
性能 50-150 粒子 + 4-5 光球,GPU 加速,移动端不卡

注意事项

  • 必须 ClientOnly 包裹,否则 SSR 报错
  • 切换季节时空粒子自动清空重置
  • 光球使用 will-change: opacity, transform 开启 GPU 合成层
  • 光球动画是纯 CSS,不占用 JS 主线程