Mac 上一直未能找到免费且好用的类似 Wallpaper Engine 的动态壁纸软件。所以直接想着自己搞一个。
本文主要记录核心技术点的实现,包括"将窗口置于桌面图标下层"、"多显示器支持"、"系统托盘常驻"。
效果展示:

功能支持
- 控制中心 (Dashboard):提供独立的控制面板,可为每个显示器单独管理壁纸。
- 丰富的媒体支持 :
- 图片:支持 JPG, PNG, GIF, WebP 等常见格式。
- 视频:支持 MP4, WebM, MKV, MOV (自动静音循环播放)。
- HTML:支持将任意本地 HTML 文件设置为交互式壁纸。
- 自动保存状态:应用重启后,自动恢复上次设置的壁纸配置。
- 历史记录:自动记录最近使用的壁纸,方便快速切换回之前的喜爱内容。
- 多显示器支持:自动检测接入的显示器,并支持多屏独立设置。
- 在线画廊:内置在线资源库,可一键下载包括《绝区零》、《原神》、《鸣潮》等热门游戏的高清静态与动态壁纸。
核心技术实现
1. 将窗口置于桌面图标下层
这是最核心的功能。Electron 的 BrowserWindow 提供了一个 type: 'desktop' 属性,在 macOS 上会将窗口置于最底层。
javascript
const win = new BrowserWindow({
type: 'desktop', // 关键配置:设置为桌面类型
enableLargerThanScreen: true,
frame: false, // 无边框
show: false, // 先隐藏,加载完再显示
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webSecurity: false // 允许加载本地资源
}
});
仅仅这样还不够,为了保证交互体验,我们需要让这个窗口无法被聚焦和移动,像真正的壁纸一样。
2. 多显示器支持
现在的开发环境通常都有多个屏幕。通过 Electron 的 screen 模块获取所有显示器,并为每个显示器创建一个独立的 BrowserWindow 实例。
javascript
const { screen } = require('electron');
const displays = screen.getAllDisplays();
displays.forEach((display) => {
createWallpaperWindow(display);
});
function createWallpaperWindow(display) {
const { x, y, width, height } = display.bounds;
const win = new BrowserWindow({
x, y, width, height, // 填满当前屏幕
// ... 其他配置
});
// 加载资源
win.loadFile('path/to/wallpaper.html');
}
3. 资源获取 (爬虫)
为了解决壁纸来源问题,内置了一个简单的爬虫(基于 Node.js fetch),抓取米游社等平台的同人图和官方壁纸。
主要难点在于处理接口的 Referer 校验和数据分页。
4. 甚至支持关闭主窗口后常驻后台
为了不让应用在关闭设置面板(主窗口)时直接退出,需要利用 Tray 模块和拦截 window-all-closed 事件。
javascript
// 拦截主窗口关闭事件,改为隐藏
mainWindow.on('close', (event) => {
if (!app.isQuitting) {
event.preventDefault();
mainWindow.hide();
}
});
// 实现托盘菜单
const tray = new Tray(iconPath);
const contextMenu = Menu.buildFromTemplate([
{ label: '打开面板', click: () => showMainWindow() },
{ label: '退出', click: () => {
app.isQuitting = true;
app.quit();
}
}
]);
tray.setContextMenu(contextMenu);
构建与分发
1. 双架构打包
为了同时支持 M1/M2/M3 (Apple Silicon) 和旧款 Intel Mac,配置了 electron-builder 的 universal 构建或分别构建。
package.json 配置:
json
"mac": {
"target": {
"target": "default",
"arch": ["x64", "arm64"]
}
}
2. "应用已损坏,无法打开" 的解决
因为没有购买 Apple 昂贵的开发者证书进行签名,编译出的 .app 在别人的电脑上运行时会被 macOS Gatekeeper 拦截,提示"应用已损坏"。
这是一个常见问题,解决方法是移除苹果的隔离属性。用户需要执行一次终端命令:
bash
sudo xattr -rd com.apple.quarantine /Applications/Wallpaper-Mac.app
源码与下载
项目已开源,虽然功能简单,但足以满足日常动态壁纸需求(支持视频、图片)。
- GitHub 地址 : github.com/zhulinghao/...
- Release 下载 : github.com/zhulinghao/...
欢迎 Star 和 PR。