问题描述

ja实现目标元素的自由拖拽效果,当鼠标移动过快,会造成鼠标脱离目标元素外(脱标)从而导致拖拽失效。

问题分析

鼠标移动过快,导致mousemove事件频繁触发,相应的事件处理函数也频繁调用,引起延迟。延迟过后由于元素的移动速度不及鼠标的移动速度,造成鼠标移动到元素外,从而触发mouseout事件,提前结束拖拽。

优化方案

将事件处理函数添加到 document 上,而非目标元素上,让 mousemove事件在有延迟的情况下仍然可以被响应即可。

将事件绑定到 document 和 body 上的区别:绑定到 document 上,当鼠标移动到菜单栏(边界)上,元素仍然可以拖动,而 body 则无效。

完整案例

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #draggableBox {
            width: 100px;
            height: 100px;
            position: absolute;
            cursor: grab;
            z-index: 98;
            border-radius: 50%;
            background-color: skyblue;
            top: 80%;
            left: 80%;
        }
    </style>
</head>
<body>
<div id="draggableBox" draggable="true"></div>
<script>
    const draggableElement = document.getElementById('draggableBox');
    let offsetX, offsetY;

    draggableElement.addEventListener('mousedown', dragMouseDown);
    draggableElement.addEventListener('mouseup', stopDrag);

    function dragMouseDown(e) {
        e.preventDefault();
        offsetX = e.clientX;
        offsetY = e.clientY;
        document.addEventListener('mousemove', elementDrag);
    }

    function elementDrag(e) {
        e.preventDefault();
        const x = offsetX - e.clientX;
        const y = offsetY - e.clientY;
        offsetX = e.clientX;
        offsetY = e.clientY;
        draggableElement.style.top = (draggableElement.offsetTop - y) + 'px';
        draggableElement.style.left = (draggableElement.offsetLeft - x) + 'px';
    }

    function stopDrag() {
        document.removeEventListener('mousemove', elementDrag);
    }
</script>
</body>
</html>

逆风微笑的代码狗
30 声望1 粉丝