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

news2024/11/15 20:11:07

文章目录

  • 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 = true
        console.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 = false
        console.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 = true
        isMouseMove = false
    })

    // 鼠标移动
    triggerELe.addEventListener('mousemove', function(e) {
        console.log('mousemove')
        isMouseMove = true
        if (isMouseDown) {
            triggerELe.style.left = e.clientX + 'px'
            triggerELe.style.top = e.clientY + 'px'
        }
    })

    // 鼠标抬起
    triggerELe.addEventListener('mouseup', function(e) {
        console.log('mouseup')
        isMouseDown = false

        if (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 = true

        beforeX = e.offsetX
        beforeY = 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 = false

        afterX = e.offsetX
        afterY = e.offsetY

        console.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 = true

        beforeX = e.offsetX
        beforeY = e.offsetY

        // 鼠标按下时的坐标
        initX = e.offsetX
        initY = 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 = false

        afterX = e.offsetX
        afterY = e.offsetY

        console.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 = true

        beforeX = e.offsetX
        beforeY = e.offsetY

        // 鼠标按下时的坐标
        initX = e.offsetX
        initY = 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 = false

        afterX = e.offsetX
        afterY = e.offsetY

        console.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 = true

        beforeX = e.offsetX
        beforeY = e.offsetY

        // 鼠标按下时的坐标
        initX = e.offsetX
        initY = 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 = false

        afterX = e.offsetX
        afterY = e.offsetY

        console.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博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s集群资源监控工具metrics-server安装

1、下载镜像 docker pull swr.cn-east-2.myhuaweicloud.com/kuboard-dependency/metrics-server:v0.6.22、在任一一个主节点上创建角色&#xff0c;执行下面语句 kubectl create clusterrolebinding kube-proxy-cluster-admin --clusterrolecluster-admin --usersystem:kube-…

免费获取GPT-4的五种工具

不可否认&#xff0c;由OpenAI带来的GPT-4已是全球最受欢迎的、功能最强大的大语言模型&#xff08;LLM&#xff09;之一。大多数人都需要使用ChatGPT Plus的订阅服务去访问GPT-4。为此&#xff0c;他们通常需要每月支付20美元。那么问题来了&#xff0c;如果您不想每月有这笔支…

移动应用程序管理的内容、原因和方式

移动应用程序管理&#xff08;MAM&#xff09;是一个术语&#xff0c;指的是管理应用程序的整个生命周期&#xff0c;包括从设备安装、更新和卸载应用程序&#xff0c;除了在整个生命周期内管理设备外&#xff0c;MAM 还包括保护应用访问的数据&#xff0c;以及在设备上发现恶意…

vue2 element el-transfer穿梭框组件支持拖拽及排序 已封装,随取随用

项目场景&#xff1a; 项目中有个功能用到穿梭框组件&#xff0c;新版本需要支持穿梭框组件排序&#xff0c;由于element2版本中的穿梭框组件本身不支持排序功能 在此不仅需要支持随意更换顺序&#xff0c;还支持从一侧拖拽至另一侧&#xff0c;具体功能效果图如下&#xff1…

Y-MODEM协议定制上位机

最近在使用N32G031和STM32F10X系列单片机进行IAP&#xff0c;使用的是Ymodem协议。单片机上的软件已经完成了&#xff0c;一般是使用secureCRT这样的工具作为上位机来进行测试&#xff0c;后来想做一个定制化的简单的上位机。在网上找了下资料&#xff0c;以下这篇文章写的使用…

能量不够,AI帮助

问CHAT&#xff1a;有关工程管理的中文参考文献 CHAT回复&#xff1a; 1. 余庆麟. (2009). 工程项目管理[M]. 北京&#xff1a; 机械工业出版社. 2. 刘宁. (2013). 工程建设管理[M]. 北京&#xff1a;清华大学出版社. 3. 谈刚&#xff0c;陈嘉春&#xff0c;尚雅凡. (2014).…

最详细的软件测试面试题整理与分析

前言 时光荏苒&#xff0c;一转眼到了2023年末尾&#xff0c;2024年也快要来了&#xff0c;人员就业市场以往的寒冬也貌似有了转暖的迹象&#xff0c;身边大批的就业人员也开始了紧张的备战之中。 近几周也和多家合作公司的HR进行了沟通&#xff0c;发现虽然岗位就业情况较去年…

2021年06月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 下图中的程序执行一次之后,“我的变量”最终的值是? A:0或者1 B:true或者false C:包含或者不包含 D:成立或者不成立 答案:B 积木“()包含()”是一个条件判断语句,它判…

Unity RenderFeature架构分析

自定义RenderFeature接口流程 URP内部ScriptableRenderPass分析 public、protected属性 renderPassEvent &#xff1a;渲染事件发生的时刻colorAttachments &#xff1a;渲染的颜色纹理列表 m_ColorAttachmentscolorAttachment &#xff1a;m_ColorAttachments[0];depthAttac…

【转载】如何在Macbook上把Ubuntu安装到移动硬盘里

我的设备系统版本、遇到的问题和解决&#xff1a; Mac&#xff1a;macOS Ventura 13.3 Ubuntu&#xff1a;22.04.3 问题&#xff1a; 按照这个教程在【3.3.10】修改完启动项后&#xff0c;Mac系统无法启动&#xff0c;Ubuntu可以正常启动。 原因&#xff1a; Mac找不到启动引导…

自己实名绑定了几个微信号?赶紧来看看

我们都明白&#xff0c;微信的重要性无处不在&#xff0c;它与我们生活的方方面面紧密相连。如今&#xff0c;微信支付已成为我们日常生活中不可或缺的一部分。无论是购物、用餐&#xff0c;还是日常消费&#xff0c;微信支付都能轻松解决。如果你担心携带现金会有遗失的风险&a…

服务台需要跟踪的3个重要指标MTBF+MTTF+MTTR

衡量标准是IT服务管理的核心&#xff0c;可提供有关运营的见解&#xff0c;并帮助确定需要持续改进的领域。通常的服务台指标有助于展示内部运营效率。例如&#xff0c;衡量在规定时间内解决问题的工单数量的 SLA 是展示服务台效率的关键因素。另一方面&#xff0c;故障指标可帮…

那些被玩烂了的设计模式

单例模式 单例模式是指一个类在一个进程中只有一个实例对象&#xff08;但也不一定&#xff0c;比如Spring中的Bean的单例是指在一个容器中是单例的&#xff09; 单例模式创建分为饿汉式和懒汉式&#xff0c;总共大概有8种写法。但是在开源项目中使用最多的主要有两种写法&am…

SPSS信度分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

HBase之Region Splitting

目录 Region Splitting步骤 Region状态过程 Region Splitting 步骤 RegionServer开始split region&#xff0c;SPLIT事务开启。RegionServer在表上获取共享读锁防止split过程中数据被修改。接着在zk中创建一个znode&#xff0c;标记为SPLITTING。Master 将会观察到该znode的创…

linux如何查看文件的hash数值

在Linux系统中&#xff0c;你可以使用各种工具来查看文件的哈希值。下面是一些常见的方法&#xff1a; md5sum命令&#xff1a; md5sum 文件名例如&#xff1a; md5sum example.txtsha1sum命令&#xff1a; sha1sum 文件名例如&#xff1a; sha1sum example.txtsha256sum命令&a…

Android 打包aar包含第三方aar 解决方案

Android 打包aar包含第三方aar 因项目需要&#xff0c;打包aar包含第三方aar&#xff0c;如果直接对module进行打包会产生一些问题。 * What went wrong: Direct local .aar file dependencies are not supported when building an AAR. The resulting AAR would be broken be…

加速你的自动化测试:3种等待方式!

在自动化测试中&#xff0c;等待是一个重要的技术&#xff0c;用于处理页面加载、元素定位、元素状态改变等延迟问题。 等待能够确保在条件满足后再进行后续操作&#xff0c;提高自动化测试的稳定性以及可靠性。 等待方式&#xff1a;显示等待、隐式等待、线程睡眠 1. 显式等…

Python丨让简历脱颖而出的关键,居然是“它”!

进入疫情后时代&#xff0c;各行各业都在力争新的发展&#xff01;财会行业亦是如此&#xff0c;浏览各大招聘网站&#xff0c;不难发现财会相关岗位的招聘要求越来越“卷”&#xff0c;那求职者如何才能让自己获得面试邀请呢&#xff1f; 答案就是&#xff1a;一份亮眼且具有…

设计模式—开闭原则

1.背景 伯特兰迈耶一般被认为是最早提出开闭原则这一术语的人&#xff0c;在他1988年发行的《面向对象软件构造》中给出。这一想法认为一旦完成&#xff0c;一个类的实现只应该因错误而修改&#xff0c;新的或者改变的特性应该通过新建不同的类实现。新建的类可以通过继承的方…