当前位置: 首页 > 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…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...