如何在JavaScript+Electron环境下获取桌面通知的尺寸(分辨率)
解决方案
Electron 的桌面通知基于系统原生通知组件渲染(Windows 为 Toast 通知、macOS 为 User Notification、Linux 为 libnotify),不属于 Electron 内置 BrowserWindow 的 DOM 树,所以调用 innerHeight、innerWidth 等 DOM 相关属性无法获取到通知的实际渲染尺寸。
核心实现思路
Electron 官方 Notification 模块没有直接暴露原生通知的尺寸接口,可通过「通知截图+像素计算」的方案实现分辨率校验,步骤如下:
- 触发对应规格的通知展示,设置 300-500ms 延迟等待系统完成通知渲染,避免捕获到半加载的内容
- 调用 Electron 的
desktopCapturer模块捕获当前整屏的视频流,提取单帧图像 - 通过系统通知的特征匹配定位通知区域:Windows 匹配通知右上角关闭按钮/通知背景色特征,macOS 匹配右上角通知中心弹出区域的固定水平坐标范围,Linux 匹配桌面右上角/右下角的通知弹出固定区域
- 对匹配到的通知区域做像素边界计算,得到实际宽高数值,和预设的三种规格预期值做差值校验,差值在 2px 以内可判定为符合预期
可直接复用的核心代码片段
const { Notification, desktopCapturer, screen } = require('electron') const Jimp = require('jimp') // 纯JS图像像素处理工具,无需外部系统依赖 // 通知尺寸校验函数,入参为对应规格的预期宽、预期高 async function verifyNotificationSize(expectedWidth, expectedHeight) { // 1. 弹出目标规格的测试通知,配置和生产环境完全一致 const testNotification = new Notification({ title: '尺寸校验测试通知', body: '用于校验实际分辨率的测试通知', // 此处补充对应规格的其他配置:图标、自定义内容、样式参数等 }) testNotification.show() // 2. 等待通知渲染完成 await new Promise(resolve => setTimeout(resolve, 400)) // 3. 捕获当前屏幕内容 const primaryDisplay = screen.getPrimaryDisplay() const [screenSource] = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: primaryDisplay.workAreaSize }) const screenImg = await Jimp.read(screenSource.thumbnail.toPNG()) const dpiScale = primaryDisplay.scaleFactor // 4. 定位通知区域计算实际尺寸(此处以macOS为例,Windows/Linux可调整匹配逻辑) const screenWidth = screenImg.getWidth() const screenHeight = screenImg.getHeight() let notifyLeft = screenWidth, notifyRight = 0, notifyTop = screenHeight, notifyBottom = 0 // 扫描右上角30%宽*40%高的区域,匹配通知半透明白色背景,可根据系统主题调整RGBA阈值 for (let x = Math.floor(screenWidth * 0.7); x < screenWidth; x++) { for (let y = 0; y < Math.floor(screenHeight * 0.4); y++) { const { r, g, b, a } = Jimp.intToRGBA(screenImg.getPixelColor(x, y)) if (r > 240 && g > 240 && b > 240 && a > 200) { notifyLeft = Math.min(notifyLeft, x) notifyRight = Math.max(notifyRight, x) notifyTop = Math.min(notifyTop, y) notifyBottom = Math.max(notifyBottom, y) } } } // 换算实际物理像素,去除DPI缩放影响 const actualWidth = Math.round((notifyRight - notifyLeft) / dpiScale) const actualHeight = Math.round((notifyBottom - notifyTop) / dpiScale) // 关闭测试通知 testNotification.close() // 允许2px的系统渲染误差 return Math.abs(actualWidth - expectedWidth) <= 2 && Math.abs(actualHeight - expectedHeight) <= 2 }
特殊场景优化
如果你的桌面端使用了自定义 HTML 通知(用 BrowserWindow 模拟原生通知样式),无需走截图匹配逻辑,直接获取通知窗口实例调用 getBounds() 方法即可拿到精确的宽高数值。
批量校验小、中、大三种规格时,两次校验之间需要留至少1s的间隔,避免上一个通知的消失动画影响下一个通知的捕获结果。
内容的提问来源于stack exchange,提问作者Les pères Lumière
相关产品推荐
相关产品推荐

