Electron 已经不算新技术,最早是 github 从 Atom 编辑器衍生出来的框架。通过编写 Javascript, HTML, CSS 能快速编译出跨系统的桌面 app。Electron 的出现使得作为前端开发工程师的我们输出范围更广。

分享最近用 Electron 做的一个基于番茄工作法的小应用,由于实现难度不大,市面上已经有非常多类似的app。我们尝试用 Electron 来实现一个。

最终效果预览:

? 工作法

番茄工作法的核心是将任务颗粒拆分到单位时间内(25分钟)可以完成,在这25分钟内专注在这个任务三,不允许做任何与任务无关的事,在任务任务完成之后可以短暂休息一会,再继续工作。

所以这个 app 的重点是让你创建任务,⏳ 25分钟,帮让 focus on 当前在做的任务。

站在巨人的肩膀上开发

尝试新技术的时候,不要从零开始学习如何搭建技术栈,先做出来,遇到问题再查。 Electron 社区有很多优秀的沉淀,工具,模板,组件,教程等等。

搜索 react 关键字,找到了 electron-react-boilerplate 这个样板库, 这个库已经集成了 reactreduxsassflowhmr 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 开发桌面效率工具相关推荐

  1. mac json格式化工具_一个在 MAC 上 iOS/Flutter 开发的辅助工具

    大家好,我是章鱼猫. 今天给大家推荐的这个开源项目,是来自于我们公众号读者的投稿,这个东西还挺好的. 如果你作为读者,也有自己的开源项目或者你也有想推荐的开源项目,都可以向我们投稿,我们就是致力于帮助 ...

  2. 前端python开发_【2020Python修炼记】前端开发之 前端工具和HTML

    [目录] 1.什么是前端 2.前端学习历程 3.HTTP协议 1.HTML简介 2.HTML文档结构 3.HTML标签分类(一) 4.HTML标签分类(二) 5.特殊符号 6.其他常用标签 一.前端开 ...

  3. electron下载失败_解决方案汇总

    文章目录 electron下载失败_解决方案汇总 `node install.js` 出错 `RequestError: connect ETIMEDOUT 20.205.243.166:443` ` ...

  4. electron 屏幕标注_屏幕 | screen (screen) – Electron 中文开发手册

    屏幕 | screen (screen) - Electron 中文开发手册 检索有关屏幕尺寸,显示,光标位置等的信息 过程:Main, Rendererready在app发射模块事件之前,您不能要求 ...

  5. python语言程序设计难不难_零基础学Python编程开发难度大吗?从哪学起?

    转行零基础学Python编程开发难度大吗?从哪学起? 近期很多小伙伴问我,如果自己转行学习Python,完全0基础能否学会呢?Python的难度到底有多大? 今天,小编就来为大家详细解读一下这个问题. ...

  6. 如何学好python基础_零基础如何学好Python开发?

    作为一个零基础小白想学好Python开发应该先确定明确目标.做好学习Python系统规划.选择适合的开发工具.进阶提升学习规划.多练多看加深对Python程序的理解,想入门一门编程语言就需要不断的进行 ...

  7. python h5开发_从零搭建移动H5开发项目实战

    从零搭建移动H5开发项目实战 前端H5的前世今身 在Pc的时代,前端技术无疑统治了大多数用户的交互界面!而在移动为王的今天,NA开发在早期占领了大多数用户的交互界面,后来逐渐的前端H5开发找到了自己的 ...

  8. java 注册探探账号_零基础手把手教你开发探探类社交软件Tinder

    原标题:零基础手把手教你开发探探类社交软件Tinder 目录介绍 1.关于项目App整体架构 1.1项目整体架构 1.1.1 目前项目使用架构 1.1.2 目前常见的架构 1.1.3 MVP架构优点及 ...

  9. Electron开发桌面应用

    由 Bazzzinga威 同学翻译自 Medium.https://medium.com/developers-writing/building-a-desktop-application-with- ...

最新文章

  1. 想学科大讯飞成为下一个业界黑马?这些项目了解一下
  2. CLLocation的distanceFromLocation方法计算地图上距离 (汇总)
  3. linux打理ftp用户,Linux中如何添加/删除FTP用户并设置权限
  4. keil4编译c语言,用keil4编译C语言代码,编译通过,但是链接时无法产生.hex文件。...
  5. 地形图如何转换为数字高程模型(DEM)
  6. 专题:数据自治开放(上)
  7. 10g的客户端从9i的服务器中导出数据时遇到上面的问题
  8. 关于项目中的封装、重构
  9. 菜鸟网工工作中对Linux系统的一点体会
  10. 软件开发应用分层、每层的作用及各层之间调用关系
  11. MySQL中数据表的查操作
  12. python实验二序列_Python学习笔记二:02序列类型的各自方法
  13. 医院耗材管理系统开发_0
  14. 计算机设备安全隐患排查,安全安全隐患排查实施方案
  15. java学习(eclipse环境的使用)
  16. Honeywell1900霍尼韦尔 扫描二维码 QT 客户端显示数据
  17. matlab之统计和机器学习工具箱
  18. 计算机收不到打印机,打印机接收不到任务,如何添加打印机
  19. java标点符号用什么意思_标点符号的使用我说他说XX说后面在什么情况下加逗号、冒号、冒号双引号、双引号或者逗号双引号等的区分问题请详细说明谢谢...
  20. 鼓励别人谈论他们自己

热门文章

  1. pandas新字段(数据列)生成、使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战
  2. 最小二乘法和最大似然估计
  3. vue 定时循环 setInterval
  4. Python2代码转换成Python3代码
  5. 图像 主轴 相关知识
  6. 人脸检测对齐--Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
  7. 行人属性--HydraPlus-Net: Attentive Deep Features for Pedestrian Analysis
  8. LeetCode 264. Ugly Number II--C++,Python解法
  9. ubuntu16.04: mininet下使用ryu当做控制器
  10. screen史上最全教程