Electron简单示例
简单实现electron应用。实现应用菜单栏、任务栏托盘程序及其右键菜单、托盘点击显示/隐藏应用、点击关闭按钮应用隐藏到托盘、注册开机启动。win及Linux下通过electron-packager打包后是一个包含可执行文件及其依赖的文件夹,需要二次制作为对应系统的安装文件,win下使用NSIS可以实现。Linux下使用electron-installer-redhat
可以进行rpm制作。Mac下electron-installer-dmg
可以将.app
制作为dmg安装包。
程序依赖
- node.js
- npm
- electron
npm install electron -g
- electron-packager
npm install -g electron-packager
打包为一个文件夹其中有应用依赖和一个可执行文件 - auto-launch
npm install --save auto-launch
开机启动 - electron-installer-dmg
npm i electron-installer-dmg -g
制作dmg安装包 - electron-installer-redhat
npm install electron-installer-redhat -g
(需要rpmbuild
通过brew install rpm
安装)制作rpm安装包 - electron-installer-debian
npm install electron-installer-debian -g
制作deb安装包
package.json
{
"name": "helloword",
"productName":"helloword",
"version": "1.0.0",
"description": "这是helloword程序",
"main": "src/main.js",
"scripts": {
"start": "electron .",
"start_dev": "electron . --debug",
"package_win": "electron-packager ./ --platform=win32 --arch=x64 --out ./OutApp --electron-version=2.0.0 --icon=./src/image/dao.ico --asar --overwrite",
"package_win32": "electron-packager ./ --platform=win32 --arch=ia32 --out ./OutApp --electron-version=2.0.0 --icon=./src/image/dao.ico --asar --overwrite",
"package_osx": "electron-packager ./ --platform=darwin --arch=x64 --out ./OutApp --electron-version=2.0.0 --icon=./src/image/dao_black.icns --asar --overwrite",
"package_linux": "electron-packager ./ --platform=linux --arch=x64 --out ./OutApp --electron-version=2.0.0 --icon=./src/image/dao_black.ico --asar --overwrite",
"package_linux32": "electron-packager ./ --platform=linux --arch=ia32 --out ./OutApp --electron-version=2.0.0 --icon=./src/image/dao_black.ico --asar --overwrite",
"make_dmg": "electron-installer-dmg OutApp/helloword-darwin-x64/helloword.app helloword --out=OutApp/ --overwrite",
"make_rpm": "electron-installer-redhat --src OutApp/helloword-linux-x64/ --dest OutApp/ --arch x86_64",
"make_rpm32": "electron-installer-redhat --src OutApp/helloword-linux-ia32/ --dest OutApp/ --arch i386",
"make_deb": "electron-installer-debian --src OutApp/helloword-linux-x64/ --dest OutApp/ --arch amd64",
"make_deb32": "electron-installer-debian --src OutApp/helloword-linux-ia32/ --dest OutApp/ --arch i386"
},
"author": "张勇波",
"license": "ISC",
"dependencies": {
"auto-launch": "^5.0.5",
"devtron": "^1.4.0"
},
"devDependencies": {
"electron": "^2.0.0",
"electron-packager": "^12.1.0",
"electron-installer-dmg": "^1.0.0",
"electron-installer-redhat": "^0.5.0",
"electron-installer-debian": "^0.8.1"
}
}
main.js
const electron = require('electron');
// const debug = /--debug/.test(process.argv[2]);
const debug = (process.argv.indexOf("--debug") >= 0);
const {
app,
BrowserWindow
} = electron;
const path = require('path')
const url = require('url')
//用一个 Tray 来表示一个图标,这个图标处于正在运行的系统的通知区 ,通常被添加到一个 context menu 上.
const Menu = electron.Menu;
const Tray = electron.Tray;
var appTray = null; //托盘程序对象
var appStatus = 'show'; //系统托盘状态标识
// powerSaveBlocker 模块是用来阻止应用系统进入睡眠模式的,因此这允许应用保持系统和屏幕继续工作.
const powerSaveBlocker = require('electron').powerSaveBlocker;
// prevent-app-suspension - 阻止应用挂起. 保持系统活跃,但是允许屏幕不亮. 用例: 下载文件或者播放音频.
// prevent-display-sleep- 阻止应用进入休眠. 保持系统和屏幕活跃,屏幕一直亮. 用例: 播放音频.
var id = powerSaveBlocker.start('prevent-app-suspension');
// powerSaveBlocker.stop(id);
//开机启动
var AutoLaunch = require('auto-launch');
var minecraftAutoLauncher = new AutoLaunch({
name: 'helloword', //应用名称
path: process.execPath, //应用绝对路径
isHidden: false, //是否隐藏启动
mac: {
useLaunchAgent: false //是否启用代理启动,默认是AppleScript启动
}
});
//提示框
const dialog = require('electron').dialog;
// dialog.showMessageBox(win, { type: "info", title: "提示", message: win.isVisible() + '' });
// 保持一个对于 window 对象的全局引用,如果你不这样做,
// 当 JavaScript 对象被垃圾回收, window 会被自动地关闭
let win = null;
//是否退出标示
var force_quit = false;
/**
* 初始化创建主浏览窗口
* @return {[type]} [description]
*/
function createWindow() {
// 创建浏览器窗口。
let browserOptions = {
width: 1000,
height: 600,
resizable: true,
// autoHideMenuBar: false, // 自动隐藏菜单栏, 除非按了Alt键
skipTaskbar: false, // 不显示在任务栏
show: false,
transparent: false, //背景透明
webPreferences: {
nodeIntegration: false
} //禁止注入node
// frame: false, //不显示边框 按钮
};
// 创建窗口
win = new BrowserWindow(browserOptions);
win.once('ready-to-show', () => {
win.show();
});
win.once('focus', () => win.flashFrame(false));
// win.show();
// 然后加载应用的 index.html。
// win.loadURL(url.format({
// pathname: path.join(__dirname, 'index.html'),
// protocol: 'file:',
// slashes: true
// }));
win.loadURL('http://zhangyb.leanote.com');
// win.loadURL(`file://${__dirname}/index.html`);
if (debug) {
win.webContents.openDevTools();
win.maximize();
require('devtron').install();
}
// 打开开发者工具。
// win.webContents.openDevTools();
// 当 window 被关闭,这个事件会被触发。
win.on('close', (e) => {
if (!force_quit) {
e.preventDefault();
hideTray();
}
// dialog.showMessageBox(win, { type: "info", title: "提示", message: (process.platform == 'darwin') + '' });
//回收BrowserWindow对象
//mac下关闭为最小化,cms+q或菜单退出为完全退出,
//win下关闭为隐藏到托盘,并移除任务栏,托盘右键退出为完全退出
// if (process.platform !== 'darwin') {
/* if (win.isMinimized()) {
win = null;
} else {
e.preventDefault();
win.minimize();
if (process.platform !== 'darwin') {
appStatus = 'hide';
appTray.setImage(path.join(__dirname, 'image/dao.png'));
win.setSkipTaskbar(true);
}
} */
// } else {
// dialog.showMessageBox(win, { type: "info", title: "提示", message: win.isVisible() + '' });
// win = null;
// }
});
win.on('resize', () => {
win.reload();
});
win.on('closed', function () {
win = null
});
}
/**
* 初始化菜单
* @return {[type]} [description]
*/
function initMenu() {
let template = [{
label: '编辑',
submenu: [{
label: '撤销',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
}, {
label: '重做',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
}, {
type: 'separator'
}, {
label: '剪切',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
}, {
label: '复制',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
}, {
label: '粘贴',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
}, {
label: '全选',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}, {
type: 'separator'
}, {
label: '退出',
accelerator: 'CmdOrCtrl+Q',
click: function () {
force_quit = true;
appTray.destroy();
app.quit();
// app.quit();
}
}]
}, {
label: '查看',
submenu: [{
label: '重载',
accelerator: 'CmdOrCtrl+R',
click: function (item, focusedWindow) {
if (focusedWindow) {
// 重载之后, 刷新并关闭所有的次要窗体
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(function (win) {
if (win.id > 1) {
win.close()
}
})
}
focusedWindow.reload()
}
}
}, {
label: '切换全屏',
accelerator: (function () {
if (process.platform === 'darwin') {
return 'Ctrl+Command+F'
} else {
return 'F11'
}
})(),
click: function (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
}
}, {
label: '切换开发者工具',
accelerator: (function () {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: function (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
}]
}, {
label: '窗口',
role: 'window',
submenu: [{
label: '最小化',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
}, {
label: '关闭',
accelerator: 'CmdOrCtrl+W',
role: 'close'
}]
}, {
label: '帮助',
role: 'help',
submenu: [{
label: '关于',
click: function () {
initAbout();
}
}, {
label: '学习更多',
click: function () {
electron.shell.openExternal('http://zhangyb.leanote.com/')
}
}]
}];
//注册菜单
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}
/**
* 创建应用托盘程序及菜单
* @return {[type]} [description]
*/
function initTrayIcon(tray_reload) {
if (tray_reload) {
// dialog.showMessageBox(win, { type: "info", title: "获取是否开机启动", message: tray_reload + '' });
//系统托盘图标目录
appTray = new Tray(path.join(__dirname, 'image/dao_black.png'));
//设置此托盘图标的悬停提示内容
appTray.setToolTip('helloword托盘程序,点击隐藏/显示应用');
}
var label_name = "开机启动";
minecraftAutoLauncher.isEnabled().then(function (isEnabled) {
if (isEnabled) {
label_name = "开机启动(已开启)";
}
//系统托盘右键菜单
var trayMenuTemplate = [{
label: label_name,
click: function () {
// dialog.showMessageBox(win, { type: "info", title: "开机启动设置", message: process.execPath + '' });
minecraftAutoLauncher.isEnabled().then(function (isEnabled) {
if (isEnabled) {
minecraftAutoLauncher.disable();
} else {
minecraftAutoLauncher.enable();
}
initTrayIcon(false);
}).catch(function (err) {
dialog.showMessageBox(win, {
type: "info",
title: "开机启动设置",
message: err + ''
});
});
}
}, {
label: '关于',
click: function () {
initAbout();
}
},
{
label: '退出',
click: function () {
force_quit = true;
appTray.destroy();
// app.quit();
app.quit(); //因为程序设定关闭为最小化,所以调用两次关闭,防止最大化时一次不能关闭的情况
}
}
];
//图标的上下文菜单
const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
//设置此图标的上下文菜单
appTray.setContextMenu(contextMenu);
}).catch(function (err) {
// handle error
});
// dialog.showMessageBox(win, { type: "info", title: "获取是否开机启动", message: label_name + '123' });
// if (process.platform === 'darwin') {
// //如果是苹果系统 托盘菜单的图标
// appTray = new Tray(path.join(__dirname, 'image/dao.png'));
// } else {
// appTray = new Tray(path.join(__dirname, 'image/dao.png'));
// }
if (process.platform !== 'darwin') {
//单击托盘图标显示/隐藏应用
appTray.on("click", function () {
if (win === null) {
createWindow()
}
//主窗口显示隐藏切换
if (win.isVisible() && appStatus === 'show') {
hideTray();
} else {
appStatus = 'show';
appTray.setImage(path.join(__dirname, 'image/dao_black.png'))
win.show();
win.setSkipTaskbar(false);
}
});
}
//系统托盘图标闪烁
// var count = 0,
// timer = null;
// timer = setInterval(function() {
// count++;
// if (count % 2 == 0) {
// appTray.setImage(path.join(trayIcon, 'dao_black.png'))
// } else {
// appTray.setImage(path.join(trayIcon, 'dao.png'))
// }
// }, 600);
}
/**
* @description 隐藏程序界面并修改托盘图标
* @author 张勇波
*/
function hideTray() {
win.hide();
if (process.platform !== 'darwin') {
appStatus = 'hide';
appTray.setImage(path.join(__dirname, 'image/dao.png'));
win.setSkipTaskbar(true);
}
}
/**
* 关于窗口初始化
* @return {[type]} [description]
*/
function initAbout() {
var win_gy = new BrowserWindow({
width: 400,
height: 300,
resizable: false,
parent: win,
modal: true,
show: false,
// transparent: true,//背景透明
frame: false //不显示边框 按钮
});
win_gy.loadURL('http://blog.leanote.com/single/zhangyb/关于');
// win_gy.loadURL(`file://${__dirname}/about.html`);
win_gy.once('ready-to-show', () => {
win_gy.show();
});
win_gy.on('blur', () => {
win_gy.close();
});
win_gy.on('closed', () => {
win_gy = null
});
}
var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) {
// 当另一个实例运行的时候,这里将会被调用,我们需要激活应用的窗口
if (win) {
if (win.isMinimized()) win.restore();
win.focus();
}
return true;
});
// 这个实例是多余的实例,需要退出
if (shouldQuit) {
app.quit();
return;
}
// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
// 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
// 否则绝大部分应用及其菜单栏会保持激活。
if (process.platform !== 'darwin') {
// app.quit();
hideTray();
}
});
app.on('before-quit', function (e) {
if (!force_quit) {
e.preventDefault();
hideTray();
/* win.hide();
if (process.platform !== 'darwin') {
appStatus = 'hide';
appTray.setImage(path.join(__dirname, 'image/dao.png'));
win.setSkipTaskbar(true);
} */
}
})
app.on('will-quit', function () {
win = null;
})
app.on('activate', () => {
// 在macOS上,当单击dock图标并且没有其他窗口打开时,
// 通常在应用程序中重新创建一个窗口。
win.show();
if (win === null) {
createWindow()
}
});
// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', () => {
createWindow(); //主程序
initMenu(); //主程序菜单
initTrayIcon(true); //托盘程序
});
问题
编写完package.json
后若启动或编译项目有cannot find module
之类的错误,可以尝试删除项目下的node_modules文件夹和package-lock.json
文件,然后在项目根目录下执行npm install