如何制作Windows桌面动态网页天气可视化壁纸?
摘要:之前做了一个网页天气可视化项目 web-weather,用 Canvas 2D + CSS 实现了雨、雪、雾、晴、阴、冰雹、沙尘暴七种天气效果,接了 Open-Meteo 的免费 API 做自动天气,还加了声音系统、世界地
之前做了一个网页天气可视化项目 web-weather,用 Canvas 2D + CSS 实现了雨、雪、雾、晴、阴、冰雹、沙尘暴七种天气效果,接了 Open-Meteo 的免费 API 做自动天气,还加了声音系统、世界地图选点、沉浸模式。做完之后我把它挂在副屏上当动态壁纸用了好一阵子——浏览器全屏,切到第二块屏幕,效果确实不错。
但"浏览器全屏"这个方案有几个很实际的问题:
• 浏览器窗口始终在最前面,Alt+Tab 会切到它
• 不小心点到桌面,壁纸就被盖住了
• 每次开机要手动打开浏览器、输地址、全屏,繁琐
• 任务栏上多一个浏览器窗口,看着碍眼
既然这个网页本身就是为"长期挂着"设计的,为什么不干脆做一个桌面应用,把它真正嵌到 Windows 桌面壁纸层?于是就有了这个项目——Weather Wallpaper。本项目基于 Lively 进行二次开发,聚焦网页天气桌面场景。
在线体验网页版:https://weather.anhejin.cn
演示视频:https://files.anhejin.cn/videos/demo.mp4
网页天气可视化做了什么
先简单回顾一下网页端的实现。详细的技术细节写过两篇文章:
• 做了一个网页天气可视化
• 做了一个网页天气可视化 2
第一篇主要解决"怎么让天气看起来像那么回事"。Canvas 2D 画粒子——雨滴是上窄下宽的梯形,风力通过 windOffset 让它斜着落;雪花飘落带正弦波摇摆,落到导航栏上会堆积,温度高了会融化;雾天是 Canvas 雾团 + CSS 烟雾纹理 + backdrop-filter 三层叠出来的;晴天有镜头光斑,位置跟太阳成镜像关系;闪电用递归算法做分叉。数据结构用 SoA + Float32Array 做连续内存访问,绘制按透明度分档批量 fill 减少 draw call,雾气纹理预渲染到离屏 Canvas。接了 Open-Meteo 的 API,浏览器定位拿经纬度,WMO 天气代码映射到视觉效果,每十分钟刷新一次。
第二篇是后续更新。声音系统全面重做——雷声用 Web Audio API 合成了七层(crack、sub-bass boom、re-strike、rolling rumble、延迟重击、远方余震),每层都是独立的音频节点链路,预生成多个变体缓存在内存里,每次打雷听起来都不完全一样。雨声、风声、雪声也不是 MP3 循环,而是多层滤波噪声合成,音量和滤波器频率跟天气参数实时联动。风向还会影响左右声道——风从右边吹,雨声就偏右耳。
新增了冰雹和沙尘暴两种极端天气。冰雹有加速下落、旋转、落地弹跳碎片、地面碎冰堆积和融化。沙尘暴分三层——350 颗不规则多边形沙粒、5 种手绘碎屑(树枝、树叶、石子、塑料片、泥块)、60 个贴地滚动的沙团——再盖一层全屏沙色蒙版。
世界地图让你点地球上任意一个点就能看那里的天气,带 24 小时和 7 天预报时间线。沉浸模式把所有 UI 藏起来,全屏只剩天气本身。
这些东西加在一起,网页端已经是一个可以打开、选地方、听天气、挂一整天的"天气体验器"了。但它始终跑在浏览器里。
为什么要做桌面应用
原因只有一个:我想让它真的变成壁纸。
不是"看起来像壁纸",是嵌到桌面图标后面那一层,和 Windows 原生壁纸占同一个位置。桌面图标在上面,网页天气在下面,任务栏正常显示,Alt+Tab 看不到它。开机自动启动,托盘常驻,不占任务栏位置。
这种需求在动态壁纸领域并不新鲜。Wallpaper Engine 早就做了,Lively Wallpaper 也是开源方案。但我不需要一个通用的动态壁纸引擎——我只需要把一个特定的网页嵌到桌面上。所以我参考了 Lively 的核心思路,用 .NET 9 + WPF + WinForms + WebView2 写了一个极简版本。
核心原理:WorkerW 窗口层
Windows 的桌面壁纸机制其实很有意思。桌面本身是一个叫 Progman(Program Manager)的窗口,桌面图标放在它的子窗口 SHELLDLL_DefView 里的 SysListView32 中。
要把自己的窗口塞到壁纸层,关键是让 Windows 创建一个 WorkerW 窗口。
