基础准备
了解electron框架的同学知道,electron主要分为两个进程,主进程和渲染进程。 主进程通过NodeJs实现底层的调用,而渲染进程则通过Chromium实现界面的渲染。详情见
功能阐述
在功能实现时,多少会遇到渲染进程与主进程的通信或者界面间的通信。接下来就实现一个最简单的类似360悬浮球效果。主要会涉及进程间通信功能、electron菜单功能等
效果图
实现思路
1.悬浮框的展示可通过变量控制,通过变量的true/false结合ipc通信控制悬浮框的show()/hide()。
2.右键点击悬浮框时,通过ipc通信打开菜单
3.由于在页面需要通过electorn.ipcRenderer()方法进行通信,而electron在页面层导入时需要remote/ipcRenderer等内置方法,所以可以通过import或者require引入electron对象。但是务必需要将BrowserWindow.webPreferences.nodeIntegration参数设置为true,否则将会报:require is not defined的错误。
4.写一个基础的悬浮框页面Suspension.vue并获取对应的页面路由pageUrl,通过new browserWindow().loadUrl(pageUrl)将页面渲染出。
5.悬浮款鼠标效果:
- 制作点击鼠标左键且移动鼠标时的滑动效果
- 制作点击鼠标右键时的菜单效果
- 实现思路: 在Suspension的元素上设置监听器,通过监听鼠标mousedown与mousemove结合来实现左键点击悬浮框且进行拖动事件的监听,以及通过监听右键的点击时间发起ipc通信,通过electron渲染菜单栏
6.主进程收到鼠标右键触发的事件后,创建菜单。
主要代码
import {BrowserWindow, ipcMain, screen, Menu, shell, app, webContents} from 'electron'
const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:3000/main_window#/suspension` : `file://${__dirname}/index.html/main_window#/suspension`;
var win = null;
//主进程js
ipcMain.on('showSuspensionWindow', () => {
if (win) {
win.showInactive();
} else {
createSuspensionWindow();
}
});
ipcMain.on('createSuspensionMenu', (e) => {
const rightM = Menu.buildFromTemplate([
{label: '功能1-1', enabled: false},
{label: '功能1-2', enabled: false},
{label: '功能1-3'},
{type: 'separator'},
{label: '功能2-1'},
{type: 'separator'},
{label: '功能3-1'},
{label: '功能3-2'},
{
label: '退出软件',
click: () => {
app.quit();
}
},
]);
rightM.popup({});
});
function createSuspensionWindow() {
win = new BrowserWindow({
width: 60,
height: 60,
type: 'toolbar', //创建的窗口类型为工具栏窗口
frame: false, //要创建无边框窗口
resizable: false, //禁止窗口大小缩放
webPreferences: {
nodeIntegration: true,
},
transparent: true, //设置透明
alwaysOnTop: true, //窗口是否总是显示在其他窗口之前
});
const size = screen.getPrimaryDisplay().workAreaSize; //获取显示器的宽高
const winSize = win.getSize(); //获取窗口宽高
win.setPosition(size.width - winSize[0], 100);
win.loadURL(winURL);
win.once('ready-to-show', () => {
win.show()
});
win.on('close', () => {
win = null;
})
}
//渲染进程vue界面
<template>
<div id="suspension">
<div class="content_body">
<div class="suspension_ball">悬浮框</div>
</div>
</div>
</template>
<script>
import {remote, ipcRenderer} from 'electron'
export default {
name: "suspension",
mounted() {
let win = remote.getCurrentWindow();
let biasX = 0;
let biasY = 0;
let that = this;
document.addEventListener('mousedown', function (e) {
switch (e.button) {
case 0:
biasX = e.x;
biasY = e.y;
document.addEventListener('mousemove', moveEvent);
break;
case 2:
ipcRenderer.send('createSuspensionMenu');
break;
}
});
document.addEventListener('mouseup', function () {
biasX = 0;
biasY = 0;
document.removeEventListener('mousemove', moveEvent)
});
function moveEvent(e) {
win.setPosition(e.screenX - biasX, e.screenY - biasY)
}
}
}
</script>
总结
- ipcMain和ipcRenderer都是EventEmitter的实例,用法上类似于emit-on的通信。
- 在渲染进程中通过import引入electron的内置方法时,需将网页窗口的BrowserWindow.webPreferences.nodeIntegration设置为true