electron+vue3全家桶+vite项目搭建【21】自定义窗口拖拽移动

引入

如果你尝试过透明窗口,并控制透明部分事件击穿,就会发现使用 drag属性样式去控制窗口拖拽会导致点击事件失效,并且带drag属性的窗口移动到另一个窗口的透明部分会有窗口乱动的各种BUG,于是,这便需要我们自己去实现窗口拖拽移动。

demo项目地址

实现思路

参考这篇文章的实现思路

同网上给出的大多数实现,利用定时器+主进程的screen.getCursorScreenPoint(),在渲染进程开始移动时,让窗口黏在鼠标上,跟随鼠标移动,当停止拖拽时清除主进程的移动定时器。

网上找到的代码有两个常见BUG:

1.windows下,系统设置=>屏幕=>缩放如果设置的不是100% 【测试发现公司60%的非开发人员的缩放都是150%~125】,会导致拖拽窗口一直放大,如下:

在这里插入图片描述

2.windows【alt+tab】或mac,在进行快捷窗口切换时,如果此时鼠标是按压状态,结束切换会导致窗口一直黏在鼠标上,如下:
在这里插入图片描述

实现步骤

已解决以上所有BUG

1.主进程监听窗口移动

  • electron\main\index.ts
  • 利用定时器实时让当前窗口黏在鼠标上
  • 通过重设窗口宽高,解决windows缩放不是100%时的缩放bug
  • 通过修改位置前判断窗口销毁,来解决窗口被删除,但定时任务未结束,导致报错 调用已销毁窗口的错误
  • 通过判断窗口是否失焦,来解决windows / 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 = screen.getCursorScreenPoint();// 清除旧的定时器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;}}
});

2.通信工具补充ipc调用

  • src\utils\electronUtils.ts
/**
* 窗口是否可以跟随鼠标移动
* @param flag
*/
export function windowMove(flag: boolean) {ipcRenderer.send("window-move-open", flag);
}

3.渲染进程封装通用拖拽组件

  • src\components\DragTool.vue
<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;/**鼠标按压 */
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;
}
</script><style scoped lang="scss"></style>

测试

直接塞个拖拽盒子

  • src\components\demo\Index.vue
<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>

最终效果如下:

  • 修复前文展示的两个BUG
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/13408.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac上 如何批量在文件名后加相同的文字?

mac上如何批量在文件名后加相同的文字&#xff1f;不管你是使用windows电脑还是使用mac电脑&#xff0c;很多小伙伴都会在电脑上进行文件批量重命名的操作&#xff0c;不过这项操作对于使用windows系统电脑的小伙伴来说会简单一些&#xff0c;因为在网上可以搜索到很多这样的教…

软考:中级软件设计师:计算机体系结构,CISC和RISC,Flynn分类,指令流水线,吞吐率,效率

软考&#xff1a;中级软件设计师:计算机体系结构 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的…

LabVIEW开发X射线图像增强

LabVIEW开发X射线图像增强 X射线图像在临床诊断中起着重要作用。但是&#xff0c;由于各种原因&#xff0c;例如不均匀&#xff0c;低照度条件和一些噪点&#xff0c;图像质量通常不是很好。因此有必要增强这些图像&#xff0c;以方便后续处理或诊断。模糊集论是开发图像处理中…

SpringBoot第19讲:SpringBoot 如何保证接口幂等

SpringBoot第19讲&#xff1a;SpringBoot 如何保证接口幂等 在以SpringBoot开发Restful接口时&#xff0c;如何防止接口的重复提交呢&#xff1f; 本文是SpringBoot第19讲&#xff0c;主要介绍接口幂等相关的知识点&#xff0c;并实践常见基于Token实现接口幂等。 文章目录 Spr…

LLaMA: Open and Efficient Foundation Language Models

背景 用最少的计算资源&#xff0c;解决了LLM大模型预测问题&#xff0c;训练了一些列的LLaMa模型&#xff0c;在参数量比较少的情况下&#xff0c;达到业界大模型效果。 主要贡献就是提升了LLM模型的训练速度和效率&#xff0c;在小容量的基础上&#xff0c;大大提升了模型的…

基于模型预测算法的混合储能微电网双层能量管理系统研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

最长公共子序列LCA

最长连续公共子序列 题目链接:3692. 最长连续公共子序列 - AcWing题库 /*解法:定义dp[i1][j1]为以a[i]结尾的字符串和b[j]结尾的字符串的最长连续公共子序列那么对于a[i] b[j]的时候 dp[i1][j1] dp[i][j]1否则为0 其他就是细枝末节 */ #include<iostream> #include<…

【底部消息红点提示】uniapp开发小程序时,使用uni.setTabBarBadge设置底部菜单的红点

一、实现的效果 功能描述&#xff1a;无论点击底部的哪个菜单栏&#xff0c;都可以看到第二个菜单栏下显示的红点通知。 如果只在人脉当前页面设置的话&#xff0c;当你在第二个菜单栏的页面中调用uni.setTabBarBadge方法设置红点后&#xff0c;切换到第一个菜单栏的页面时&am…

基础算法-前缀和

1 算法笔记 2.代码示例 3.代码解析 #include<iostream> using namespace std; const int maxn 1010000; int a[maxn],s[maxn];//a数组是用来存放数组的&#xff0c;s是用来存放前n项数组的和 int m,n;int main(){scanf("%d%d",&n,&m);for(int i1;i&l…

怎么用转转大师工具旋转PDF文件页面

有时候我们会在网上下载一下PDF格式文件&#xff0c;下载的PDF文件中可能会出现页面倒过来的情况&#xff0c;遇到这种情况我们需要先将PDF文件旋转到正确的角度才能继续阅读使用&#xff0c;那么有哪些方法可以快速旋转PDF页面呢&#xff1f; 可以使用转转大师工具快速旋转PD…

Django_测试模块(六)

目录 开始写我们的第一个测试 首先得有个 Bug 创建一个测试来暴露这个 bug 运行测试 修复这个 bug 更全面的测试 测试视图 针对视图的测试 Django 测试工具之 Client 改善视图代码 测试新视图 测试 DetailView 集中管理用例文件 使用Django测试运行器 源码等资料…

蓝桥杯专题-试题版含答案-【数数小木块】【精挑细选】【国王的魔镜】【字符串逆序输出】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…