为什么要(zuo)
”世界上只有一种英雄主义,那就是认清自己的发际线之后依然热爱撸码“ -- 欧大强·罗兰
是一个非常有趣的开源项目,“它可以让你使用纯 JavaScript 调用丰富的原生(操作系统) APIs 来创造桌面应用”
。光看这官方简介就让人不住跃跃欲试,再加上市面上没找到能让我中意的桌面吸色工具,所以我决定使用Electron来开发一款。
需求与界面
我的软件,界面一定要好看,LOGO一定要大气,主色调要那种低沉性感又不失庄重,气势磅礴的黑。
(献丑了。果然设计师不是随便就能做的)
功能大致包括以下几点
支持快捷键操作并可自定义。
有历史选色记录。
能自由切换色值。
在已知透明度和背景色的条件下计算出当前取色器的rgba色值。
支持最小化到托盘
基本思路
Electron没有API可以直接拿到当前指针所在位置的色值,但是提供了获取桌面资源的方法。在执行取色操作时使用desktopCapturer
将当前桌面截图,然后在canvas
上展示并使用getImageData()
获取指定色值。Easy。
遇到的问题
关于Electron的介绍网络有很多,上手难度也不算高,线程之间的关系与操作还有API文档写的非常详细,但这不意味着你(zuo)起来就能一帆风顺了。
Global变量无法获取
通过ipc和global我们很容易就能实现一个简易的状态管理机制,在这里我碰到了第一个坑。
因为remote复制对象而不是提供引用,所以在渲染进程中操作的global对象需要提前在主进程中定义初始值。 main process:global.sharedObj = { prop1: null};复制代码
renderer process:
remote.getGlobal('sharedObj').prop1 = 125;复制代码
使用desktopCapturer截图有色差
通过desktopCapturer.getSources()
API我们可以得到一个对象,再配合getUserMedia
我们可以很方便的获取当前可用资源。
// In the renderer process.const { desktopCapturer } = require('electron')desktopCapturer.getSources({ types: ['window', 'screen'] }, (error, sources) => { ... navigator.mediaDevices.getUserMedia({ ... video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: sources[0].id, ... } } }).then((stream) => { const video = document.querySelector('video') video.srcObject = stream }).catch((e) => ...)})复制代码
以上是官方给的,将video
的第一帧绘制到canvas
上便成功对当前桌面进行截图。但事情并没有这么简单,在我阅片无数的双眼下,任何细微的差别都无处遁行,使用getUserMedia
得到的图像竟然有色差
DesktopCapturerSource
对象上的 thumnail(NativeImage)
能直接得到当前桌面的缩略图(截图)并且没有色差, 但是desktopCapturer
在工作中是会阻塞进程的,不推荐直接通过 thumnail
来获取百分百比例的桌面截图。所以最后我选择使用 desktop-screenshot
这个第三方node库来实现截图步骤。 写入文件路径报错
我使用了lowdb
这个node库来储存设置的快捷键和历史色值,开发的时候一切正常,可打包后在Mac上运行起来就会报错EROFS: read-only file system
app.getPath(name) // Electron or os.tmpdir() // node原生模块获得临时文件路径复制代码
打包优化
除了尽可能减少dependencies
的依赖之外,基本无解。别问,问就是100M起。
结尾
虽然这是一个简单的项目,还有很多没来得及深入发掘。
虽然常伴小坑,但总的来说瑕不掩瑜,体验还是相当到位的。 如果你也想体验一把桌面应用开发,Electron是个非常靠谱的选择。参考资料: