electron 托盘图标闪烁_从零到一,用 Electron 开发桌面效率工具
Electron 已经不算新技术,最早是 github 从 Atom 编辑器衍生出来的框架。通过编写 Javascript, HTML, CSS 能快速编译出跨系统的桌面 app。Electron 的出现使得作为前端开发工程师的我们输出范围更广。
分享最近用 Electron 做的一个基于番茄工作法的小应用,由于实现难度不大,市面上已经有非常多类似的app。我们尝试用 Electron 来实现一个。
最终效果预览:
? 工作法
番茄工作法的核心是将任务颗粒拆分到单位时间内(25分钟)可以完成,在这25分钟内专注在这个任务三,不允许做任何与任务无关的事,在任务任务完成之后可以短暂休息一会,再继续工作。
所以这个 app 的重点是让你创建任务,⏳ 25分钟,帮让 focus on 当前在做的任务。
站在巨人的肩膀上开发
尝试新技术的时候,不要从零开始学习如何搭建技术栈,先做出来,遇到问题再查。 Electron 社区有很多优秀的沉淀,工具,模板,组件,教程等等。
搜索 react 关键字,找到了 electron-react-boilerplate 这个样板库, 这个库已经集成了 react
, redux
, sass
, flow
, hmr
webpack
等工具,同时准备好 electron-builder
打包工具,作为 electron
新手,我们优先选择开箱即用的工具,快速开启业务开发。
SVG 和 React Component
大概画了一下草图,准备进入开发阶段。考虑后面会用到 svg icon,先在 FlatIcon 上找些免费的图标,下载 SVG 文件。
通过 SVGR 在线工具导入 svg 内容生成 React Component 代码。(svgr 也有 cli 等工具)
用 SVG Component 的好处是可以在代码上更灵活地控制样式,相比 png 图标可交互性强,复用率高。
托盘和托盘弹窗
这个 app 启动的时候就隐藏在托盘菜单的一角,点击的时候显示 BrowserWindow,通过 Electron 提供的方法,可以获得托盘和托盘弹窗的 Bounds 信息,设置坐标位置。
const tray = new Tray(path.join(__dirname, '../static', 'tray.png'));
const mainWindow = new BrowserWindow({
frame: false,
resizable: true,
transparent: true
});
const showWindow = () => {
const { x, y } = getPositionFromActiveDisplay();
mainWindow.setPosition(x, y, true);
mainWindow.show();
};
const getPositionFromActiveDisplay = () => {
const trayBounds = tray.getBounds();
const windowBounds = mainWindow.getBounds();
const x = Math.round(trayBounds.x + trayBounds.width / 2 - windowBounds.width / 2);
const y = Math.round(trayBounds.y + trayBounds.height);
return { x, y };
};
?图的三角是由前端代码绘制的,加上 frame 和 electron 背景色,应该长这样。
渲染线程和主线程
app 需要倒计时功能,告诉用户距离任务完成时间还有多久。Electron 有渲染进程和主线程,BrowserWindow 不可见的时候,渲染进程会尽量减少消耗,所以如果 Tick 在渲染进程的话,当 app 处于后台时会出现非常大的时间偏差。这里使用 Electron 提供的 ipcMain 和 ipcRenderer 做进程通信。
在主线程每秒发送 Tick 事件
// main.js
ipcMain.once('store-ready', event => {
const run = () => {
setTimeout(() => {
run();
event.sender.send('tick');
}, 1000);
};
run();
});
渲染进程就收事件并将 dispatch TICK action。
// app/index.js
const store = configureStore({
tasks: electronStore.getTasks()
});
ipcRenderer.send('store-ready');
ipcRenderer.on('tick', () => {
store.dispatch({
type: TICK
});
});
redux store 里面判断当前执行的任务计算倒计时时间。
switch (action.type) {
case TICK:
return {
...state,
rows: state.rows.map(task =>
task.id === state.currentId
? {
...task,
remain: Math.max(task.remain - 1, 0)
}
: task
)
};
数据持久存储
数据持久化有很多种方案,因为是前端浏览器,我们可以选择 localStorage, Cookie,indexDB 等等。考虑可靠性,持久化以及存储空间,还可以通过 Electron 写文件的方式,把数据写入到应用路径下。这样即使 app 被卸载了,只要数据没被清空,用户数据还在。
通过 Electron app getPath 可以获得应用存储路径
import { app } from 'electron';
app.getPath('userData');
mac 下应用 app 的路径是 /Users/user/Library/ApplicationSupport/focus
。更简单的方式可以直接用开源库 electron-store
,以 key-value
的格式存储 json 文件。
{
"tasks": {
"rows": [
{
"name": "任务名称",
"id": "91ac7f05-76f4-46ea-addb-f392a3a29b54",
"created_at": 1553398427806,
"plan": 1500,
"remain": 0,
"done": true
}
],
"currentId": "91ac7f05-76f4-46ea-addb-f392a3a29b54"
}
}
倒计时 UI
有些样式可能用 css 实现难度较大,而用 svg 的方式实现起来非常简单。比如倒计时 UI,路径圆角和路径长度用 CSS 实现复杂度较高。可以在 Sketch 上直接绘制处理,导出成 svg,直接通过 react 代码控制。
export default function(props: Props) {
const offset = percentage * totalLength;
const cx =
Math.cos(percentage * Math.PI * 2 - Math.PI * 0.5) * radius + radius;
const cy =
Math.sin(percentage * Math.PI * 2 - Math.PI * 0.5) * radius + radius;
return (
...others
<circle
id="path-1"
cx={cx}
cy={cy}
r="32"
fill="white"
style={{ transition: '1s linear' }}
/>
<path
...others
strokeLinecap="round"
strokeDasharray={totalLength}
strokeDashoffset={offset}
style={{ transition: '1s linear' }}
/>
svg>
);
}
临界状态判断
app 在任务时间结束时需要有 Notification,由于?的 Tick 设计,判断任务是否完成可以放在 redux middleware 上。
// middlewares/tasks
export default ({ getState }) => next => action => {
if (typeof action === 'object' && action.type === 'TICK') {
const beforeCount = getTimeEndTaksCount(getState);
next(action);
const afterCount = getTimeEndTaksCount(getState);
if (beforeCount !== afterCount) {
new Notification('Focus,任务完成了吗?');
}
} else {
next(action);
}
};
经过一个 Tick action 之后,判断任务完成数是否有变化,并使用 HTML5 Notification 通知用户。
Travis CI
功能开发完毕之后,使用 electron-builder
进行打包发布,构建之后推到 github release 下,用户可以直接在这下载到最新的包。
同样的, boilerplate
已经准备好 .travis.yml
文件,唯一需要我们操作的是在 https://github.com/settings/tokens/new 上生成 token,在 https://www.travis-ci.org/ 构建之前配置 Environment Variables
, GH_TOKEN
tirgger build, 成功之后就能看到构建成功过的包,下载使用
总结
使用 Electron,前端开发者可以使用自己的武器构建跨系统的桌面端应用,而且不用学习其他技术,缺点是一个小小的功能打包完的体积是 70M。
这个 app 从有想法到最终实现比预期的简单,感兴趣的同学也可以自己 DIY 些小玩意儿。完整的代码在 github 上https://github.com/HelKyle/focus,欢迎体验,同时也欢迎 star~
作者:HelKyle
https://juejin.im/post/5c966596e51d454d42032ce9
electron 托盘图标闪烁_从零到一,用 Electron 开发桌面效率工具相关推荐
- mac json格式化工具_一个在 MAC 上 iOS/Flutter 开发的辅助工具
大家好,我是章鱼猫. 今天给大家推荐的这个开源项目,是来自于我们公众号读者的投稿,这个东西还挺好的. 如果你作为读者,也有自己的开源项目或者你也有想推荐的开源项目,都可以向我们投稿,我们就是致力于帮助 ...
- 前端python开发_【2020Python修炼记】前端开发之 前端工具和HTML
[目录] 1.什么是前端 2.前端学习历程 3.HTTP协议 1.HTML简介 2.HTML文档结构 3.HTML标签分类(一) 4.HTML标签分类(二) 5.特殊符号 6.其他常用标签 一.前端开 ...
- electron下载失败_解决方案汇总
文章目录 electron下载失败_解决方案汇总 `node install.js` 出错 `RequestError: connect ETIMEDOUT 20.205.243.166:443` ` ...
- electron 屏幕标注_屏幕 | screen (screen) – Electron 中文开发手册
屏幕 | screen (screen) - Electron 中文开发手册 检索有关屏幕尺寸,显示,光标位置等的信息 过程:Main, Rendererready在app发射模块事件之前,您不能要求 ...
- python语言程序设计难不难_零基础学Python编程开发难度大吗?从哪学起?
转行零基础学Python编程开发难度大吗?从哪学起? 近期很多小伙伴问我,如果自己转行学习Python,完全0基础能否学会呢?Python的难度到底有多大? 今天,小编就来为大家详细解读一下这个问题. ...
- 如何学好python基础_零基础如何学好Python开发?
作为一个零基础小白想学好Python开发应该先确定明确目标.做好学习Python系统规划.选择适合的开发工具.进阶提升学习规划.多练多看加深对Python程序的理解,想入门一门编程语言就需要不断的进行 ...
- python h5开发_从零搭建移动H5开发项目实战
从零搭建移动H5开发项目实战 前端H5的前世今身 在Pc的时代,前端技术无疑统治了大多数用户的交互界面!而在移动为王的今天,NA开发在早期占领了大多数用户的交互界面,后来逐渐的前端H5开发找到了自己的 ...
- java 注册探探账号_零基础手把手教你开发探探类社交软件Tinder
原标题:零基础手把手教你开发探探类社交软件Tinder 目录介绍 1.关于项目App整体架构 1.1项目整体架构 1.1.1 目前项目使用架构 1.1.2 目前常见的架构 1.1.3 MVP架构优点及 ...
- Electron开发桌面应用
由 Bazzzinga威 同学翻译自 Medium.https://medium.com/developers-writing/building-a-desktop-application-with- ...
最新文章
- 想学科大讯飞成为下一个业界黑马?这些项目了解一下
- CLLocation的distanceFromLocation方法计算地图上距离 (汇总)
- linux打理ftp用户,Linux中如何添加/删除FTP用户并设置权限
- keil4编译c语言,用keil4编译C语言代码,编译通过,但是链接时无法产生.hex文件。...
- 地形图如何转换为数字高程模型(DEM)
- 专题:数据自治开放(上)
- 10g的客户端从9i的服务器中导出数据时遇到上面的问题
- 关于项目中的封装、重构
- 菜鸟网工工作中对Linux系统的一点体会
- 软件开发应用分层、每层的作用及各层之间调用关系
- MySQL中数据表的查操作
- python实验二序列_Python学习笔记二:02序列类型的各自方法
- 医院耗材管理系统开发_0
- 计算机设备安全隐患排查,安全安全隐患排查实施方案
- java学习(eclipse环境的使用)
- Honeywell1900霍尼韦尔 扫描二维码 QT 客户端显示数据
- matlab之统计和机器学习工具箱
- 计算机收不到打印机,打印机接收不到任务,如何添加打印机
- java标点符号用什么意思_标点符号的使用我说他说XX说后面在什么情况下加逗号、冒号、冒号双引号、双引号或者逗号双引号等的区分问题请详细说明谢谢...
- 鼓励别人谈论他们自己
热门文章
- pandas新字段(数据列)生成、使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战
- 最小二乘法和最大似然估计
- vue 定时循环 setInterval
- Python2代码转换成Python3代码
- 图像 主轴 相关知识
- 人脸检测对齐--Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
- 行人属性--HydraPlus-Net: Attentive Deep Features for Pedestrian Analysis
- LeetCode 264. Ugly Number II--C++,Python解法
- ubuntu16.04: mininet下使用ryu当做控制器
- screen史上最全教程