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

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

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

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

  1. 示例代码
<!DOCTYPE html>
<html lang="en">
<head&gt;
    <meta charset="UTF-8"&gt;
    <meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    <title&gt;测试拖拽</title&gt;
    <style&gt;
        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博客

原文地址:https://blog.csdn.net/dongzi_yu/article/details/134601011

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_17063.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注