electron 无边框窗口拖拽移动问题及解决办法
作者:IT老大哥
electron 无边框窗口拖拽移动问题记录及解决办法
在做一款uTools的插件,悬浮文本
窗口是没有标题栏的,所以需要找一个地方可以拖动移动位置
就开始了接下来的踩坑记录
项目结构
只是一个简单的容器元素,一个多行文本框
容器元素加一个内边距,然后这个内边距区域就是我理想的可拖动位置
<body> <div id="container"> <textarea id="content" spellcheck="false"></textarea> </div> </body>
实现流程
webkit-app-region
首个版本,我采用CSS很简单便实现了
当时是用 Mac 开发测试的,一切运行良好
#container { -webkit-app-region: drag; padding: 10px; cursor: move; }
隔天到 Win 上看效果
发现拖动虽然正常,但是光标样式没有了
鼠标放在边框位置不会变成移动的光标
经查阅,设置了-webkit-app-region: drag;
的元素,不会在响应鼠标事件了(mac上测试的时候正常的)
so,需要继续改了
鼠标事件
没有简便办法了,就只好自己写个鼠标拖拽事件了
按下记录下鼠标相对于窗口的位置
鼠标移动后计算出窗口新的位置
窗口新位置
=窗口当前位置
+鼠标新的相对位置
-鼠标原来的相对位置
主进程 (因为是uTools
插件开发,和electron
原始代码的监听不一样)
ipcRenderer.on('move', (event, x, y) => { ubWindow.setPosition(x, y) }) // 初始化 ipcRenderer.sendTo(ubWindow.webContents.id, 'init')
webPreferences
的preload
const { ipcRenderer } = require('electron') let winId ipcRenderer.on('init', (event) => { winId = event.senderId window.init() }) window.move = (x, y) => { ipcRenderer.sendTo(winId,'move',x, y) }
页面js
let moveIng = false let startX = 0 let startY = 0 const move = (event) => { if (!moveIng) return const x = window.screenX + event.clientX - startX const y = window.screenY + event.clientY - startY window.move(x, y) } //绑定拖拽移动事件 document.addEventListener('mousedown', (event) => { if (event.button === 0 && event.target.tagName !== 'TEXTAREA') { moveIng = true startX = event.clientX startY = event.clientY document.addEventListener('mousemove', move) } }) document.addEventListener('mouseup', (event) => { if (!moveIng) return document.removeEventListener('mousemove', move) moveIng = false })
测试,Win和Mac拖拽正常,光标正常
But,换电脑在测试时,发现某个Win的电脑移动窗口时,窗口尺寸会不停的变大
甚至只要鼠标按在窗口上,尺寸都可能会改变
so,继续改吧
缩放
经过多次测试和查阅
最终把问题定位在Win的缩放与布局
该选项如果是100%
测试一点问题都没有
如果每次拖动尺寸会发生改变,那我们就不再使用setPosition
改用setBounds
每次调整位置时直接将尺寸也传递进去,修改下代码
主进程
ipcRenderer.on('moveBounds', (event, x, y, width, height) => { if (event.senderId == ubWindow.webContents.id) { let newBounds = { x: parseInt(x), y: parseInt(y), width: parseInt(width), height: parseInt(height), } ubWindow.setBounds(newBounds) } }) // 初始化 ipcRenderer.sendTo(ubWindow.webContents.id, 'init')
webPreferences
的preload
const { ipcRenderer } = require('electron') let winId ipcRenderer.on('init', (event) => { winId = event.senderId window.init() }) window.moveBounds = (x, y, width, height) => { ipcRenderer.sendTo(winId, 'moveBounds', x, y, width, height); }
页面js
let moveIng = false let startX = 0 let startY = 0 let lastWidth = 0 let lastHeight = 0 const move = (event) => { if (!moveIng) return const x = window.screenX + event.clientX - startX const y = window.screenY + event.clientY - startY window.moveBounds(parseInt(x), parseInt(y), lastWidth, lastHeight) } //绑定拖拽移动事件 document.addEventListener('mousedown', (event) => { if (event.button === 0 && event.target.tagName !== 'TEXTAREA') { moveIng = true startX = parseInt(event.clientX) startY = parseInt(event.clientY) lastWidth = parseInt(window.outerWidth) lastHeight = parseInt(window.outerHeight) document.addEventListener('mousemove', move) } }) document.addEventListener('mouseup', (event) => { if (!moveIng) return document.removeEventListener('mousemove', move) moveIng = false })
调整后Win和Mac测试均正常
但如果拖动过快,仔细观察,窗口有时会闪烁
而且文本框中的内容有时会变成选中状态
嗯~ o(* ̄▽ ̄*)o
暂时就酱吧
有大神知道更好解决方案的话可以贴出来观摩下
补充:
Electron无边框自定义窗口拖动
解决方案
<header class="absolute" style="left:0px;top:0px;width:100%;height:48px;background-color:red;padding:0px;margin:0px;"> <div class="absolute" style="left:0px;top:0px;width:100%;height:100%;-webkit-app-region:drag"> <button style="width:200px;height:100px;-webkit-app-region:no-drag;" @click="console.log('abc')">点我</button> </div> </header>
首先外部可拖拽区域设置:-webkit-app-region:drag;
如果想要里面的按钮可点击,仅需要设置按钮不可拖拽就行:-webkit-app-region:drag;
到此这篇关于electron 无边框窗口拖拽移动问题记录及解决办法的文章就介绍到这了,更多相关electron 无边框窗口拖拽移动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!