用 Electron 写了一个 macOS 版本的 wallpaper(附源码、下载地址)

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

源码与下载

项目已开源,虽然功能简单,但足以满足日常动态壁纸需求(支持视频、图片)。

欢迎 Star 和 PR。

相关推荐
满天星辰15 小时前
Typescript之类型总结大全
前端·typescript
JFChen15 小时前
Web 仔用 Node 像 Java 一样写后端服务
前端
XiaoSong15 小时前
React useState 原理和异步更新
前端·react.js
徐徐子15 小时前
从vue3 watch开始理解Vue的响应式原理
前端·vue.js
眯眼因为很困啦15 小时前
GitHub Fork 协作完整流程
前端·git·前端工程化
whisper15 小时前
🚀 React Router 7 + Vercel 部署全指南
前端
还债大湿兄16 小时前
huggingface.co 下载有些要给权限的模型 小记录
开发语言·前端·javascript
叶落无痕5216 小时前
Electron应用自动化测试实例
前端·javascript·功能测试·测试工具·electron·单元测试
卡布叻_星星16 小时前
Vue3+Vite+Electron实现开发桌面应用
electron