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
暂时就酱吧
有大神知道更好解决方案的话可以贴出来观摩下