当前位置: 首页 > news >正文

鼠标拖拽问题,不选中文本不触发单击事件

文章目录

  • 1. 为什么鼠标单击的时候触发了`mousemove`事件?明明鼠标没有移动
  • 2. 鼠标拖拽元素怎么能不触发单击事件?怎么处理鼠标在元素内的相对定位,而不是每次定位到左上角?
    • 方式一:拖拽的元素没有注册click监听就不会触发单击事件绑定的函数
    • 方式二:通过鼠标是否发生移动判断当前元素是需要移动还是需要单击
    • 方式三:考虑鼠标在元素内相对定位问题,鼠标点击位置就是拖拽位置
  • 3. 鼠标拖拽元素怎么能不触发选中文本?
    • 方式一:鼠标按下时,阻止默认事件`e.preventDefault()`,不触发选中文本
    • 方式二:鼠标按下时,修改当前元素style样式,鼠标抬起再取消
  • 参考链接

        鼠标拖拽需要注意什么问题?
        鼠标拖拽会依次触发mousedown mousemove mouseup click事件。很多时候在一个元素既需要拖拽又需要单击的时候,应该怎么避免在拖拽时不触发单击事件?不触发文本选中问题?

1. 为什么鼠标单击的时候触发了mousemove事件?明明鼠标没有移动

2. 鼠标拖拽元素怎么能不触发单击事件?怎么处理鼠标在元素内的相对定位,而不是每次定位到左上角?

方式一:拖拽的元素没有注册click监听就不会触发单击事件绑定的函数

  1. 示例代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>测试拖拽</title><style>body{background-color: #f5f5f5;}#triggerDiv {position: fixed;left: 0px;top: 0px;width: 100px;height: 100px;background-color: red;position: absolute;text-align: center;line-height: 100px;vertical-align: middle;cursor: pointer;border-radius: 50%;}</style>
</head>
<body><div id="triggerDiv">拖拽</div>
</body><script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {isMouseDown = trueconsole.log('mousedown:', isMouseDown)})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove:', isMouseDown)if (isMouseDown) {triggerELe.style.left = e.clientX + 'px'triggerELe.style.top = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {isMouseDown = falseconsole.log('mouseup:', isMouseDown)})// 鼠标离开:事件顺序 mouseout > mouseleave// triggerELe.addEventListener('mouseout', function(e) {//     isMouseDown = false//     console.log('mouseout:', isMouseDown)// })// triggerELe.addEventListener('mouseleave', function(e) {//     isMouseDown = false//     console.log('mouseleave:', isMouseDown)// })// 给元素绑定了单击事件// triggerELe.addEventListener('click', function(e) {//     console.log('click')// })
</script>
</html>
  1. 通过对比是否绑定单击事件,判断单击是否被触发

image.pngimage.png

方式二:通过鼠标是否发生移动判断当前元素是需要移动还是需要单击

  1. 如果mousemove事件没有被触发,那mouseup发生时当前元素应该执行单击事件
    1. 示例代码
<script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false // 鼠标是否按下let isMouseMove = false // 鼠标是否发生移动// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {console.log('mousedown')isMouseDown = trueisMouseMove = false})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove')isMouseMove = trueif (isMouseDown) {triggerELe.style.left = e.clientX + 'px'triggerELe.style.top = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {console.log('mouseup')isMouseDown = falseif (isMouseMove) {console.log('鼠标移动了')} else {console.log('鼠标没有移动,执行单击事件')}})
</script>
  1. 通过判断是否触发mousemove事件,决定是否执行单击事件

image.png

  1. 如果mousedownmouseup事件发生后,鼠标位置没有改变应该执行单击事件
    1. 示例代码
<script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false // 鼠标是否按下// ========= 鼠标移动相关变量 ===========let beforeX = 0 // 鼠标按下时的x坐标let beforeY = 0 // 鼠标按下时的y坐标let afterX = 0 // 鼠标抬起时的x坐标let afterY = 0 // 鼠标抬起时的y坐标// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {console.log('mousedown')isMouseDown = truebeforeX = e.offsetXbeforeY = e.offsetY})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove')if (isMouseDown) {triggerELe.style.left = e.clientX + 'px'triggerELe.style.top = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {console.log('mouseup')isMouseDown = falseafterX = e.offsetXafterY = e.offsetYconsole.log('beforeX:', beforeX, 'beforeY:', beforeY, 'afterX:', afterX, 'afterY:', afterY)// 前后坐标相等,说明没有移动,执行单击事件if (beforeX !== afterX || beforeY !== afterY) {console.log('鼠标移动了')} else {console.log('鼠标没有移动,执行单击事件')}})// // 给元素绑定了单击事件// triggerELe.addEventListener('click', function(e) {//     console.log('click')// })
</script>
  1. 思路:如果鼠标前后坐标没有发生变化执行单击事件

image.png
注!由于页面缩放问题,可能会出现鼠标没有移动但是前后坐标不一致的问题。

方式三:考虑鼠标在元素内相对定位问题,鼠标点击位置就是拖拽位置

<script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false // 鼠标是否按下// ========= 鼠标移动相关变量 ===========let beforeX = 0 // 鼠标按下时的x坐标let beforeY = 0 // 鼠标按下时的y坐标let afterX = 0 // 鼠标抬起时的x坐标let afterY = 0 // 鼠标抬起时的y坐标let initX = 0 // 鼠标按下时的x坐标let initY = 0 // 鼠标按下时的y坐标// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {console.log('mousedown')isMouseDown = truebeforeX = e.offsetXbeforeY = e.offsetY// 鼠标按下时的坐标initX = e.offsetXinitY = e.offsetY})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove')if (isMouseDown) {triggerELe.style.left = (e.clientX - initX) + 'px'triggerELe.style.top = (e.clientY - initY) + 'px'// 鼠标移动时的坐标afterX = e.offsetX + 'px'afterY = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {console.log('mouseup')isMouseDown = falseafterX = e.offsetXafterY = e.offsetYconsole.log('beforeX:', beforeX, 'beforeY:', beforeY, 'afterX:', afterX, 'afterY:', afterY)// 前后坐标相等,说明没有移动,执行单击事件if (beforeX !== afterX || beforeY !== afterY) {console.log('鼠标移动了')} else {console.log('鼠标没有移动,执行单击事件')}})// // 给元素绑定了单击事件// triggerELe.addEventListener('click', function(e) {//     console.log('click')// })
</script>

3. 鼠标拖拽元素怎么能不触发选中文本?

方式一:鼠标按下时,阻止默认事件e.preventDefault(),不触发选中文本

<script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false // 鼠标是否按下// ========= 鼠标移动相关变量 ===========let beforeX = 0 // 鼠标按下时的x坐标let beforeY = 0 // 鼠标按下时的y坐标let afterX = 0 // 鼠标抬起时的x坐标let afterY = 0 // 鼠标抬起时的y坐标let initX = 0 // 鼠标按下时的x坐标let initY = 0 // 鼠标按下时的y坐标// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {console.log('mousedown')isMouseDown = truebeforeX = e.offsetXbeforeY = e.offsetY// 鼠标按下时的坐标initX = e.offsetXinitY = e.offsetY// 阻止默认事件e.preventDefault()})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove')if (isMouseDown) {triggerELe.style.left = (e.clientX - initX) + 'px'triggerELe.style.top = (e.clientY - initY) + 'px'// 鼠标移动时的坐标afterX = e.offsetX + 'px'afterY = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {console.log('mouseup')isMouseDown = falseafterX = e.offsetXafterY = e.offsetYconsole.log('beforeX:', beforeX, 'beforeY:', beforeY, 'afterX:', afterX, 'afterY:', afterY)// 前后坐标相等,说明没有移动,执行单击事件if (beforeX !== afterX || beforeY !== afterY) {console.log('鼠标移动了')} else {console.log('鼠标没有移动,执行单击事件')}})// // 给元素绑定了单击事件// triggerELe.addEventListener('click', function(e) {//     console.log('click')// })
</script>

方式二:鼠标按下时,修改当前元素style样式,鼠标抬起再取消

<script>let triggerELe = document.getElementById('triggerDiv')let isMouseDown = false // 鼠标是否按下// ========= 鼠标移动相关变量 ===========let beforeX = 0 // 鼠标按下时的x坐标let beforeY = 0 // 鼠标按下时的y坐标let afterX = 0 // 鼠标抬起时的x坐标let afterY = 0 // 鼠标抬起时的y坐标let initX = 0 // 鼠标按下时的x坐标let initY = 0 // 鼠标按下时的y坐标// 鼠标按下triggerELe.addEventListener('mousedown', function(e) {console.log('mousedown')isMouseDown = truebeforeX = e.offsetXbeforeY = e.offsetY// 鼠标按下时的坐标initX = e.offsetXinitY = e.offsetY// 不选中文字triggerELe.style.userSelect = 'none'// 添加css// css// .no-select {//  user-select: none// }})// 鼠标移动triggerELe.addEventListener('mousemove', function(e) {console.log('mousemove')if (isMouseDown) {triggerELe.style.left = (e.clientX - initX) + 'px'triggerELe.style.top = (e.clientY - initY) + 'px'// 鼠标移动时的坐标afterX = e.offsetX + 'px'afterY = e.clientY + 'px'}})// 鼠标抬起triggerELe.addEventListener('mouseup', function(e) {console.log('mouseup')isMouseDown = falseafterX = e.offsetXafterY = e.offsetYconsole.log('beforeX:', beforeX, 'beforeY:', beforeY, 'afterX:', afterX, 'afterY:', afterY)// 前后坐标相等,说明没有移动,执行单击事件if (beforeX !== afterX || beforeY !== afterY) {console.log('鼠标移动了')// 移除css// .no-select {//  user-select: text// }triggerELe.style.userSelect = 'text'} else {console.log('鼠标没有移动,执行单击事件')}})// // 给元素绑定了单击事件// triggerELe.addEventListener('click', function(e) {//     console.log('click')// })
</script>

参考链接

可拖动DIV层的实现方法_可拖动的div-CSDN博客
Javascript设置拖拽时不触发点击事件_鼠标拖动列表,会触发列表项的点击事件,如何阻止-CSDN博客

相关文章:

鼠标拖拽问题,不选中文本不触发单击事件

文章目录 1. 为什么鼠标单击的时候触发了mousemove事件&#xff1f;明明鼠标没有移动2. 鼠标拖拽元素怎么能不触发单击事件&#xff1f;怎么处理鼠标在元素内的相对定位&#xff0c;而不是每次定位到左上角&#xff1f;方式一&#xff1a;拖拽的元素没有注册click监听就不会触发…...

Java 之 final 详解

目录 一. 前言 二. final 的基础使用 2.1. 修饰类 2.2. 修饰方法 2.2.1. private 方法是隐式的 final 2.2.2. final 方法可以被重载 2.3. 修饰参数 2.4. 修饰变量 2.4.1. static final 2.4.2. blank final 2.4.3. 所有 final 修饰的字段都是编译期常量吗&#xff1f…...

数据分析策略

文章目录 我想对比不同完整度40%&#xff0c;50%&#xff0c;60%抽样计算来10min的TI序列&#xff0c;它们的差异与完整率的关系&#xff0c;告诉我怎么对比即可 了解您的分析目标后&#xff0c;我可以提供一个比较不同完整度&#xff08;40%&#xff0c;50%&#xff0c;60%&am…...

子虔科技亮相2023工业软件生态大会 以先进理念赋能工业软件发展

作为云化工业软件领先企业&#xff0c;子虔科技携多项全新云原生产品亮相2023工业软件生态大会。 本届大会以“共建新一代工业软件体系&#xff0c;引领制造业高质量发展”为主题&#xff0c;集结行业领先企业、行业专家探究工业软件在核心技术、产业链创新和生态建设等方面创…...

《C++PrimePlus》第9章 内存模型和名称空间

9.1 单独编译 Visual Studio中新建头文件和源代码 通过解决方案资源管理器&#xff0c;如图所示&#xff1a; 分成三部分的程序&#xff08;直角坐标转换为极坐标&#xff09; 头文件coordin.h #ifndef __COORDIN_H__ // 如果没有被定义过 #define __COORDIN_H__struct pola…...

FFmpeg常用命令讲解及实战二

文章目录 前言一、ffmpeg 常用命令1、ffmpeg 的封装转换2、ffmpeg 的编转码3、ffmpeg 的基本编转码原理 二、ffprobe 常用参数1、show_format2、show_frames3、show_streams4、print_format5、select_streams 三、ffplay 的常用命令1、ffplay 常用参数2、ffplay 高级参数3、ffp…...

Django之Cookie与Session,CBV加装饰器

前言 会话跟踪技术 在一个会话的多个请求中共享数据&#xff0c;这就是会话跟踪技术。例如在一个会话中的请求如下&#xff1a;  请求银行主页&#xff1b; 请求登录&#xff08;请求参数是用户名和密码&#xff09;&#xff1b;请求转账&#xff08;请求参数与转账相关的数…...

定时发朋友圈怎么发?

...

nodejs 将word转为pdf office-to-pdf

jspdf用于html转pdf。需借助html2canvas遍历页面中的dom节点,渲染成canvas image&#xff0c;再用jspdf把图片转为pdf。office-to-pdf 用于word转pdf。依赖于libreOffice&#xff0c;需提前安装 mac安装libreOffice 1.首先需要jdk8,并配置环境变量 2.再就是需要安装libreOf…...

12.docker的网络-host模式

1.docker的host网络模式简介 host模式下&#xff0c;容器将不会虚拟出自己的网卡、配置IP等&#xff0c;而是使用宿主机的IP和端口&#xff1b;也就说&#xff0c;宿主机的就是我的。 2. 以host网络模式创建容器 2.1 创建容器 我们仍然以tomcat这个镜像来说明一下。我们以h…...

如何在外部数据库中存储空间化表时使用Mapinfo_mapcatalog

开始创建地图目录表之前 您将使用EasyLoader在要使用的数据库中创建地图目录表。EasyLoader与MapInfo Pro一起安装。 &#xff08;工具“DBMS_Catalog”不再随MapInfo Professional 64位一起提供&#xff0c;因为它的功能可以在EasyLoader工具中找到。&#xff09; ​ 注&…...

从Github登录的双因子验证到基于时间戳的一次性密码:2FA、OTP与TOTP

Github于2023-03-09推出一项提高软件安全标准的措施&#xff0c;所有在Github上贡献过代码的开发人员在年底前必须完成 2FA&#xff08;Two-factory authentication&#xff0c;双因子认证&#xff09;。初听此事之时&#xff0c;不以为意&#xff0c;因为自己之前就知道双因子…...

ubuntu22.04安装wvp-gb28181-pro 2023-11-23最新版本(一键安装)

下载程序 输入下面命令&#xff0c;输入普通用户密码&#xff0c;切换到 root用户 sudo su git clone -b ubuntu_wvp_online_install_2023_0425 https://gitcode.net/zenglg/ubuntu_wvp_online_install.git 等待下载完成 安装 进入到克隆下来的路径中 cd /home/tuners/ub…...

Spring Boot 应用的 Docker 化:从 Maven 构建到 Docker 部署的完整指南

1. 使用Dockerfile部署 # 使用Java 8基础镜像 FROM java:8 LABEL authors"mabh"# 设置时区为Asia/Shanghai&#xff0c;可以根据需要更改 ENV TIME_ZONEAsia/Shanghai# 更新时区 RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_…...

linux之chmod命令

在linux系统中经常遇到需要对文件修改读写执行的权限&#xff0c;下面对chomod命令进行梳理总结。 1、文件权限 在linux系统中&#xff0c;每个文件都有归属的所有者和所有组&#xff0c;并且规定了文件的所有者、以及其他人对文件所拥有的可读&#xff08;r&#xff09;、可写…...

论文阅读 Forecasting at Scale (一)

最近在看时间序列的文章&#xff0c;回顾下经典 论文地址 项目地址 Forecasting at Scale 摘要1、介绍2、时间业务序列的特点3、Prophet预测模型3.1、趋势模型3.1.1、非线性饱和增长3.1.2、具有变化点的线性趋势3.1.3、自动转换点选择3.1.4、趋势预测的不确定性 摘要 预测是一…...

Unity PlayerPrefs相关应用

PlayerPrefs是Unity游戏引擎中的一个类&#xff0c;用于在游戏中存储和访问玩家的偏好设置和数据。它可以用来保存玩家的游戏进度、设置选项、最高分数等信息。PlayerPrefs将数据存储在本地文件中&#xff0c;因此可以在游戏重新启动时保持数据的持久性。 //PlayerPrefs的数据…...

LeetCode题解:13. 罗马数字转整数,哈希表,JavaScript,详细注释

原题链接&#xff1a;13. 罗马数字转整数 解题思路&#xff1a; 本题涉及到的罗马数字都是唯一的&#xff0c;因此可以创建一个哈希表&#xff0c;存储罗马数字和整数的对应关系。遍历s&#xff0c;分别截取从i开始的2位和1位字符串&#xff0c;查看其在哈希表中的罗马数字对…...

GPT2-chitchat项目运行

git clone https://github.com/yangjianxin1/GPT2-chitchat.git把项目拉下来 下载模型文件&#xff1a; 从[模型分享]中下载模型文件&#xff0c;例如 model_epoch40_50w。 将模型文件放到正确的位置&#xff1a; 将下载的模型文件夹 model_epoch40_50w 放到项目的 model 目录…...

selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(3)

接前一篇文章:selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(2) 4. 重点文件内容解析 (1)control/postist文件 上一回讲解了postinst文件的前一部分内容,本回继续往下解析。为了便于理解,再次贴出postinst完整代码: #!/bin/sh set -e# summary of ho…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...