electron-vue 制作悬浮球
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
1、background.js配置文件
'use strict'
import {updateHandle} from './utils/update.js';
import ElectronStore from 'electron-store'
import { app, protocol, ipcMain,screen, BrowserWindow,globalShortcut } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import electronDefaultData from './config/electron-default-data'
const isDevelopment = process.env.NODE_ENV !== 'production'
global.$winodws = {
main: null
}
const electron = require('electron')
const Menu = electron.Menu
let win,ball
let electronStore
protocol.registerStandardSchemes(['app'], { secure: true })
function createWindow() {
showBallWindow();
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
app.quit()
})
app.on('quit', () => {
app.quit()
})
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
}
// 初始化配置文件
electronStore = new ElectronStore({
defaults: electronDefaultData,
cwd: app.getPath('userData')
})
global.electronStore = electronStore
createWindow()
})
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
//进入主页
ipcMain.on('mainPage',function(){
showMainPage();
})
//显示悬浮球
ipcMain.on('show_ball',function(){
win=null
if (ball) {
if (ball.isVisible()) {
showBallWindow();
} else {
ball.showInactive();
}
} else {
showBallWindow();
}
})
//显示主页
function showMainPage(){
if(win==null){
let size = screen.getPrimaryDisplay().workAreaSize
let width = parseInt(size.width)
let height = parseInt(size.height)
let appWidth=parseInt(width/3)
Menu.setApplicationMenu(null)
win = new BrowserWindow({
width: appWidth,
height: height,
x:width-appWidth,
y:0,
closable:true,
frame: false,
alwaysOnTop: true,
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true,
webSecurity: false
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
} else {
win.loadURL('app://./index.html')
}
globalShortcut.register('CmdOrCtrl+T', () => {
win.webContents.openDevTools();
})
}else {
win.focus()
win.show()
}
}
function showBallWindow() {
if(ball==null){
ball = new BrowserWindow({
width: 175,
height: 65,
type: 'toolbar', //创建的窗口类型为工具栏窗口
frame: false, //要创建无边框窗口
resizable: false, //禁止窗口大小缩放
show: true, //先不让窗口显示
webPreferences: {
devTools: true,
nodeIntegration: true,
enablemotemodule: true,
webSecurity: false
},
transparent: true, //设置透明
alwaysOnTop: true,
});
const size = screen.getPrimaryDisplay().workAreaSize; //获取显示器的宽高
const winheight = parseInt(size.height)
const winSize = ball.getSize(); //获取窗口宽高
//设置窗口的位置 注意x轴要桌面的宽度 - 窗口的宽度
ball.setPosition(size.width - winSize[0]-5, winheight-100);
if (process.env.WEBPACK_DEV_SERVER_URL) {
ball.loadURL(process.env.WEBPACK_DEV_SERVER_URL+'#/ball');
} else {
createProtocol('app')
ball.loadURL('app://./index.html'+ '#/ball')
}
ball.once('ready-to-show', () => {
ball.show()
});
ball.on('close', () => {
ball = null;
})
globalShortcut.register('CmdOrCtrl+Y', () => {
ball.webContents.openDevTools();
})
//更新软件
updateHandle(ball);
}else {
ball.focus()
ball.show()
}
}
ipcMain.on('createSuspensionMenu', (e) => {
const rightM = Menu.buildFromTemplate([
{
label: '显示主页',
click: () => {
showMainPage();
}
},{
label: '关闭主页',
click: () => {
if(win!=null){
win.hide()
}
}
}
]);
rightM.popup({});
});
//登录窗口最小化
ipcMain.on('window-min',function(){
win.minimize();
})
//登录窗口最大化
ipcMain.on('window-max',function(){
if(win.isMaximized()){
win.restore();
}else{
win.maximize();
}
})
//TODO 置顶
ipcMain.on('window-top', () => {
win.setAlwaysOnTop(false);
});
//关闭应用
ipcMain.on('window-close', () => {
app.quit()
});
//隐藏窗口
ipcMain.on('win-hide', () => {
if(win!=null){
win.hide()
}
});
//显示窗口
ipcMain.on('win-show', () => {
showMainPage()
});
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
if (!win) {
showMainPage()
}
if (win.isMinimized()) win.restore()
win.focus()
win.show()
sendUpdateMessage({
cmd: 'second-instance-msg',
message: commandLine,
})
})
}
//给渲染进程发送消息
function sendUpdateMessage(text) {
if(win!=null){
win.webContents.send('message', text)
}
}
//给渲染进程发送消息
function sendBallUpdateMessage(text) {
if(ball!=null){
ball.webContents.send('message', text)
}
}
2、路由模式
import Vue from 'vue'
import Router from 'vue-router'
import { asyncRouterMap } from '@/config/router.config'
// hack router push callback
const originalPush = Router.prototype.push
Router.prototype.push = function push (location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
Vue.use(Router)
const $router = new Router({
// mode: 'history',
base: process.env.BASE_URL,
routes: asyncRouterMap,
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0}
}
})
// 解决Loading chunk (\d)+ failed问题
$router.onError((error) => {
const pattern = /Loading chunk (\d)+ failed/g;
const isChunkLoadFailed = error.message.match(pattern);
if(isChunkLoadFailed){
// 用路由的replace方法,并没有相当于F5刷新页面,失败的js文件并没有从新请求,会导致一直尝试replace页面导致死循环,而用 location.reload 方法,相当于触发F5刷新页面,虽然用户体验上来说会有刷新加载察觉,但不会导致页面卡死及死循环,从而曲线救国解决该问题
location.reload();
// const targetPath = $router.history.pending.fullPath;
// $router.replace(targetPath);
}
});
export default $router;
3、悬浮球页面
功能:右侧菜单事件,拖拽,双击进入主页
<template>
<div class="content_body" >
<div class="ball">
<div @dblclick="goMainPage" >
<span style="color: transparent">1</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "ball",
data () {
return {
}
},
created() {
let win;
let biasX ;
let biasY;
if (navigator.userAgent.indexOf('Electron') != -1) {
const remote = require('electron').remote
const {ipcRenderer: ipc} = require('electron');
win= remote.getCurrentWindow();
biasX = 0;
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:
ipc.send('createSuspensionMenu')
break;
}
});
document.addEventListener('mouseup', function () {
biasX = 0;
biasY = 0;
document.removeEventListener('mousemove', moveEvent)
});
}
function moveEvent(e) {
if (navigator.userAgent.indexOf('Electron') != -1) {
if(win!=null){
win.setPosition(e.screenX - biasX, e.screenY - biasY)
}
}
}
},
methods: {
goMainPage () {
if (navigator.userAgent.indexOf('Electron') != -1) {
const {ipcRenderer: ipc} = require('electron');
ipc.send('mainPage')
}
}
},
}
</script>
<style>
body{
background-color: transparent;
}
* {
padding: 0;
margin: 0;
}
.ball {
background: url("../../assets/ballbg.png") no-repeat;
}
.content_body {
position: relative;
text-align: center;
line-height: 65px;
/* 过渡效果在IE下展示效果不友好 */
transition: all 0.08s;
user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
top: 0%;
left: 0%;
}
</style>
GitHub 加速计划 / vu / vue
82
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
9e887079
[skip ci] 2 个月前
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
更多推荐
已为社区贡献4条内容
所有评论(0)