工具栏悬浮

This commit is contained in:
zdg 2024-07-26 12:48:03 +08:00
parent fe21b676a8
commit d50d4722aa
9 changed files with 207 additions and 65 deletions

View File

@ -3,10 +3,11 @@ import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
import File from './file'
import * as Tool from './tool'
// 代理 electron/remote
import remote from '@electron/remote/main' // 第一步引入remote
remote.initialize() // 第二步: 初始化remote
// 第一步引入remote
import remote from '@electron/remote/main'
// 第二步: 初始化remote
remote.initialize()
File({ app, shell, BrowserWindow, ipcMain })
@ -63,6 +64,9 @@ function createMainWindow() {
mainWindow.on('ready-to-show', () => {
mainWindow.show()
})
mainWindow.on('closed', () => {
mainWindow = null
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
@ -74,6 +78,8 @@ function createMainWindow() {
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
// mainWindow.setAlwaysOnTop(true, "screen-saver") // 将窗口设置为顶层窗口
// mainWindow.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见
// 第三步: 开启remote服务
remote.enable(mainWindow.webContents)
}
@ -162,7 +168,6 @@ app.on('ready', () => {
}
loginWindow.destroy()
loginWindow = null
Tool.setWin({mainWindow}) // 将主窗口传递到工具类中
})
// 打开登录窗口
ipcMain.on('openLoginWindow', () => {
@ -178,8 +183,7 @@ app.on('ready', () => {
ipcMain.on('openWork', (e, data) => {
createWork(data)
})
// zdg: 创建工具窗口-如 悬浮球
Tool.init()
// 打开-登录窗口
createLoginWindow()
app.on('activate', function () {

View File

@ -14,7 +14,6 @@ let allWindow = {}
export function init() {
// 创建工具-悬浮球
ipcMain.on('tool-sphere:create', async(e, data) => {
console.log('xxx', allWindow)
// console.log('测试xxxx', data)
await createTools(data) // 执行逻辑
e.reply('tool-sphere:create-reply', {code: 200, msg: 'success'}) // 返回结果
@ -56,7 +55,7 @@ export function init() {
// url = 'https://www.baidu.com'
console.log(urlAll)
win.loadURL(urlAll)
// win.setFullScreen(true) // 设置窗口为全屏
win.setFullScreen(true) // 设置窗口为全屏
win.setIgnoreMouseEvents(true) // 忽略鼠标事件|使窗口不可选中
win.once('ready-to-show', () => {
win.show()
@ -77,14 +76,3 @@ export function setWin(win = {}) {
})
}
}
// 工具窗口-特殊区域恢复鼠标
function toolMouse(toolWin) {
ipcMain.on('tool-mouse', (e, data) => {
const { id } = data
const win = allWindow[id]
if (win) {
win.setIgnoreMouseEvents(false)
}
})
}

View File

@ -13,6 +13,12 @@ export const toolRouters = [
name: 'toolSphere',
meta: {title: '悬浮球'}
},
{
path: 'test',
component: () => import('@/views/tool/test.vue'),
name: 'toolTest',
meta: {title: '测试'}
},
]
},
{

View File

@ -118,6 +118,7 @@ export const useBoardStore = defineStore(
// init background | 初始化背景
initBackground() {
const backgroundColor = FabricVue?.canvas?.backgroundColor
console.log('xxxx', backgroundColor, FabricVue?.canvas)
if (backgroundColor && typeof backgroundColor === 'string') {
const type = colorUtils.getColorFormat(backgroundColor)
if (type === 'hex') {
@ -131,9 +132,13 @@ export const useBoardStore = defineStore(
this.backgroundOpacity = opacity
}
} else if (FabricVue?.canvas) {
FabricVue.canvas.backgroundColor = 'rgba(255, 255, 255, 1)'
this.backgroundColor = 'rgba(255, 255, 255, 1)'
this.backgroundOpacity = 1
if (this.backgroundColor) {
FabricVue.canvas.backgroundColor = this.backgroundColor
} else {
FabricVue.canvas.backgroundColor = 'rgba(255, 255, 255, 1)'
this.backgroundColor = 'rgba(255, 255, 255, 1)'
this.backgroundOpacity = 1
}
}
const backgroundImage = FabricVue?.canvas?.backgroundImage

View File

@ -1,11 +1,16 @@
/**
* @description: electron 封装的工具函数
*/
const { ipcRenderer } = window.electron || {}
// const {getCurrentWindow,BrowserWindow, shell, app} = require('@electron/remote');
import remote from '@electron/remote'
const remote = require('@electron/remote')
console.log('xxxxx ', remote)
// const { ipcRenderer } = window.electron || {}
// import { ipcRenderer } from 'electron' // 渲染器里面可以使用ipcRenderer
// const path = require('path')
const Remote = require('@electron/remote')
// 常用变量
const BaseUrl = process.env['ELECTRON_RENDERER_URL']+'/#'
const isDev = process.env.NODE_ENV !== 'production'
/**
* @description 消息发送-nodejs 消息发送
* @form src/main/tool.js 来源
@ -25,20 +30,117 @@ export function ipcMsgSend(key, data) {
ipcRenderer.send(key, data)
})
}
export function test() {
// console.log(BrowserWindow)
// const win = new BrowserWindow({
// width: 400, height: 400
// })
// win.loadURL('https://www.baidu.com')
// win.show()
// win.on('close', () => {
// win = null
// })
// const url = app.getPath('userData')+'/123.pdf'
// console.log(app.getPath('userData'))
// shell.openExternal(url)
const win = getCurrentWindow()
console.log(win)
/**
* 创建-窗口 调用该方法
* @param {*} type 类型
* tool-sphere 创建-悬浮球
* @param {*} data 参数
* @returns
*/
export const createWindow = async (type, data) => {
if (!type) return console.error('createWindow: type is null')
switch(type) {
case 'tool-sphere': { // 创建-悬浮球
const option = data.option||{}
const defOption = {
frame: false, // 要创建无边框窗口
resizable: false, // 禁止窗口大小缩放
transparent: true, // 设置透明
alwaysOnTop: true, // 窗口是否总是显示在其他窗口之前
// parent: mainWin, // 父窗口
// autoClose: true, // 关闭窗口后自动关闭
}
data.option = {...defOption, ...option}
const win = await toolWindow(data)
win.show()
win.setFullScreen(true) // 设置窗口为全屏
win.setIgnoreMouseEvents(true, {forward: true}) // 忽略鼠标事件但是事件继续传递给窗口
win.setAlwaysOnTop(true,'screen-saver') // 将窗口设置为顶层窗口
win.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见
// win.webContents.openDevTools() // 打开调试工具
eventHandles(type, win) // 事件监听处理
return win
}
default:
break
}
}
/**
* @description: 基础-创建工具-窗口
* @param {*} url 路由地址
* @param {number} [width=800] 窗口宽度
* @param {number} [height=600] 窗口高度
* @param {{}} [option={}] 自定义选项
* @author: zdg
* @date 2021-07-05 14:07:01
*/
export function toolWindow({url, isFile, isConsole, option={}}) {
// width = window.screen.width
let width = option?.width || 800
let height = option?.height || 600
const mainWin = Remote.getCurrentWindow() // 获取主窗口对象
const devUrl = `${BaseUrl}${url}`
const buildUrl = `file://${__dirname}/index.html${url}`
const urlAll = isDev ? devUrl : buildUrl
return new Promise((resolve) => {
const config = {
width, height,
type: 'toolbar', // 创建的窗口类型为工具栏窗口
webPreferences: {
preload: '@root/src/preload/index.js',
nodeIntegration: true, // nodeApi调用
contextIsolation: false, // 沙箱取消
// webSecurity: false // 跨域关闭
},
...option
}
// 创建-新窗口
let win = new Remote.BrowserWindow(config)
if (!!isFile) win.loadFile(urlAll) // 加载文件
else win.loadURL(urlAll) // 加载url
win.once('ready-to-show', () => {resolve(win)})
// 主窗口关闭事件
mainWin.once('closed', () => { win.destroy()})
// 内部监听器
win.webContents.on('did-finish-load', () => {})
// 内部监听器-是否打印
if (!!isConsole) {
win.webContents.on('console-message', (e,leve,m,lin,s) => {
console.log('console-msg: ', m)
})
}
})
}
/**
* 窗口创建-事件处理
* @param {*} type 事件类型
* @param {*} win 窗口对象
*/
const eventHandles = (type, win) => {
// 公共方法
const publicMethods = ({onClosed}) => {
// 监听关闭事件
Remote.ipcMain.once('close-window', () => {win.destroy()})
win.on('closed', () => {!!onClosed && onClosed();win = null})
}
switch(type) {
case 'tool-sphere': { // 创建-悬浮球
// 监听设置穿透
const setIgnore = (_, ignore) => {win.setIgnoreMouseEvents(ignore, {forward: true})}
Remote.ipcMain.on('tool-sphere:set:ignore', setIgnore)
// 关闭窗口
Remote.ipcMain.once('tool-sphere:close', () => { win.destroy() })
// 放大监听-测试
Remote.ipcMain.once('maximize-window', () => {
win.destroy()
console.log('关闭窗口')
})
const on = {
onClosed: () => {Remote.ipcMain.off('tool-sphere:set:ignore', setIgnore)}
}
publicMethods(on) // 加载公共方法
break}
default:
break
}
}

View File

@ -16,7 +16,7 @@
</div>
<!-- 上传弹窗 -->
<uploadDialog v-model="isDialogOpen" @submitFile="submitFile" />
<!-- <el-button @click="testClick">测试</el-button> -->
<el-button @click="testClick">测试</el-button>
</template>
<script setup>
@ -27,11 +27,11 @@ import ResoureSearch from './container/resoure-search.vue'
import ResoureList from './container/resoure-list.vue'
import uploadDialog from '@/components/upload-dialog/index.vue'
import uploaderState from '@/store/modules/uploader'
import { ipcMsgSend, test } from '@/utils/tool'
import { createWindow } from '@/utils/tool'
const sourceStore = useResoureStore()
const isDialogOpen = ref(false)
const testClick = () => {console.log('xxxx');test()}
const openDialog = () => {
isDialogOpen.value = true
}
@ -40,6 +40,11 @@ onMounted(async () => {
// const res = await ipcMsgSend('tool-sphere:create', params)
// console.log('', res)
})
const testClick = async() => {
const params = { url: '/tool/sphere' }
const win = await createWindow('tool-sphere', params)
console.log('消息返回:', win)
}
//
const getData = (data) => {
const { textBook, node } = data

View File

@ -0,0 +1,24 @@
<template>
<canvas ref="canvasRef" />
<slot></slot>
</template>
<script setup>
//
import { ref, onMounted } from 'vue'
import { FabricVue } from '@/plugins/fabric'
import { useBoardStore } from '@/store/modules/draw'
const canvasRef = ref(null)
onMounted(async() => {
if (canvasRef.value) {
useBoardStore().backgroundColor = 'transparent'
const option = { freeDrawingCursor: 'default' }
await FabricVue.initCanvas(canvasRef.value, option)
// FabricVue.canvas.backgroundColor = 'transparent'
// FabricVue.canvas.setWidth(500)
// FabricVue.canvas.setHeight(500)
}
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,11 +1,10 @@
<template>
<div class="warp-all">
<el-row class="tool-bottom-all">
<board-vue></board-vue>
<!-- 底部工具栏 -->
<el-row id="test" class="tool-bottom-all" @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
<el-col :span="3" class="flex justify-center items-center">
<div class="c-logo">
<el-image :src="logo"></el-image>
</div>
<div class="c-logo"><el-image :src="logo" @click="tabChange('close')" /></div>
</el-col>
<el-col :span="20">
<el-segmented class="c-btns" v-model="tabActive" :options="btnList" size="large" block
@ -24,8 +23,13 @@
<script setup>
// electron
import { ref } from 'vue'
import logo from '@root/resources/icon.png'
import { onMounted, ref } from 'vue'
import logo from '@root/resources/icon.png' // logo
import boardVue from './components/board.vue'
// const Remote = require('@electron/remote') // remote
const { ipcRenderer } = require('electron')
const tabActive = ref('select')
const btnList = [
{ label: '选择', value: 'select', icon: 'icon-mouse' },
@ -38,7 +42,7 @@ const btnList = [
// ==== ===
const tabChange = (val) => { // tab-change
console.log(val)
console.log('xxxx', val)
switch (val) {
case 'brush':
break
@ -50,10 +54,18 @@ const tabChange = (val) => { // 切换tab-change
break
case 'more':
break
case 'close':
ipcRenderer.send('tool-sphere:close')
break
default:
break
}
}
const mouseChange = (bool) => { // 穿
let resBool = false
if (tabActive.value == 'select') resBool = !!bool
ipcRenderer.send('tool-sphere:set:ignore', resBool)
}
</script>
<style lang="scss" scoped>

View File

@ -1,26 +1,22 @@
<template>
<div>
xxxxx
</div>
<canvas ref="canvasRef" />
<canvas class="test" ref="canvasRef" />
</template>
<script setup>
// electron
import { ref, onMounted } from 'vue'
import { FabricVue } from '@/plugins/fabric'
// import * as fabricStore from '@/store/modules/draw'
// let useDrawStore = fabricStore.useDrawStore()
// console.log(useDrawStore)
import { useBoardStore } from '@/store/modules/draw'
let canvasRef = ref(null)
onMounted(async() => {
console.log(canvasRef, FabricVue)
if (canvasRef.value) {
const option = { width: 400, height: 400, freeDrawingCursor: 'default' }
useBoardStore().backgroundColor = 'transparent'
const option = { freeDrawingCursor: 'default' }
await FabricVue.initCanvas(canvasRef.value, option)
FabricVue.canvas.setWidth(500)
FabricVue.canvas.setHeight(500)
// FabricVue.canvas.setWidth(500)
// FabricVue.canvas.setHeight(500)
}
})