赞
踩
2023/07/16 DragTool组件补充鼠标移除事件,添加延时器,避免卡顿的情况下,鼠标滑出移动范围,但窗口仍跟随鼠标移动
如果你尝试过透明窗口,并控制透明部分事件击穿,就会发现使用 drag属性样式去控制窗口拖拽会导致点击事件失效,并且带drag属性的窗口移动到另一个窗口的透明部分会有窗口乱动的各种BUG,于是,这便需要我们自己去实现窗口拖拽移动。
同网上给出的大多数实现,利用定时器+主进程的screen.getCursorScreenPoint(),在渲染进程开始移动时,让窗口黏在鼠标上,跟随鼠标移动,当停止拖拽时清除主进程的移动定时器。
网上找到的代码有两个常见BUG:
1.windows下,系统设置=>屏幕=>缩放如果设置的不是100% 【测试发现公司60%的非开发人员的缩放都是125%~150%】,会导致拖拽窗口一直放大,如下:
2.windows【alt+tab】或mac,在进行快捷窗口切换时,如果此时鼠标是按压状态,结束切换会导致窗口一直黏在鼠标上,如下:
已解决以上所有BUG
/** 窗口移动功能封装 */ // 窗口移动 位置刷新定时器 let movingInterval = null; /** * 窗口移动事件 */ ipcMain.on("window-move-open", (event, canMoving) => { let winStartPosition = { x: 0, y: 0 }; let mouseStartPosition = { x: 0, y: 0 }; const currentWindow = getWindowByEvent(event); const currentWindowSize = currentWindow.getSize(); if (currentWindow) { if (canMoving) { // 读取原位置 const winPosition = currentWindow.getPosition(); winStartPosition = { x: winPosition[0], y: winPosition[1] }; // 获取当前鼠标聚焦的窗口 mouseStartPosition = BrowserWindow.getFocusedWindow(); // 清除旧的定时器 if (movingInterval) { clearInterval(movingInterval); } // 创建定时器,每10毫秒更新一次窗口位置,保证一致 movingInterval = setInterval(() => { // 窗口销毁判断,高频率的更新有可能窗口已销毁,定时器还没结束,此时就会出现执行销毁窗口方法的错误 if (!currentWindow.isDestroyed()) { // 如果窗口失去焦点,则停止移动 if (!currentWindow.isFocused()) { clearInterval(movingInterval); movingInterval = null; } // 实时更新位置 const cursorPosition = screen.getCursorScreenPoint(); const x = winStartPosition.x + cursorPosition.x - mouseStartPosition.x; const y = winStartPosition.y + cursorPosition.y - mouseStartPosition.y; // 更新位置的同时设置窗口原大小, windows上设置=>显示设置=>文本缩放 不是100%时,窗口会拖拽放大 currentWindow.setBounds({ x: x, y: y, width: currentWindowSize[0], height: currentWindowSize[1], }); } }, 10); } else { clearInterval(movingInterval); movingInterval = null; } } });
/**
* 窗口是否可以跟随鼠标移动
* @param flag
*/
export function windowMove(flag: boolean) {
ipcRenderer.send("window-move-open", flag);
}
<template> <div @mouseenter="mouseenter" @mouseleave="mouseleave" @mousedown="mousedown" @mouseup="mouseup" > <slot></slot> </div> </template> <script setup lang="ts"> import electronUtils from "@/utils/electronUtils"; // 鼠标进入判断,只有鼠标进入到范围内,才能进行鼠标按压拖拽 let enterFlag = false; // 鼠标按压判断,只有鼠标进入范围内,并且按压状态,此时释放鼠标才会关闭窗口移动 let mousedownFlag = false; let timer: NodeJS.Timeout | null; /**鼠标按压 */ function mousedown() { if (enterFlag) { electronUtils.windowMove(true); mousedownFlag = true; } } /**鼠标释放 */ function mouseup() { if (enterFlag && mousedownFlag) { electronUtils.windowMove(false); mousedownFlag = false; } } /**鼠标移入 */ function mouseenter() { enterFlag = true; } /**鼠标移出 */ function mouseleave() { enterFlag = false; // 避免卡顿的情况下,鼠标滑出移动范围,但窗口仍跟随鼠标移动 if (timer !== null) { timer = setTimeout(() => { mousedownFlag = false; electronUtils.windowMove(false); timer = null; }, 1000); } } </script> <style scoped lang="scss"></style>
直接塞个拖拽盒子
<template>
<drag-tool>
<div class="drag-box">拖拽区域</div>
</drag-tool>
</template>
<style scoped lang="scss">
.drag-box {
width: 200px;
height: 50px;
border: 1px solid #ccc;
background: pink;
margin: 0 auto;
user-select: none;
}
</style>
最终效果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。