原生JS快速拖动元素失效问题

快速拖动元素失效问题缘由及解决方法

情景再现

晚上在写毕设时,碰到个快速拖动元素,元素会跟不上的问题。具体情形以下:html

代码及演示结果

  • 出现的问题

    clipboard.png

  • 绑定在 documentbody

    clipboard.png

  • 绑定在 div 本身身上

    clipboard.png

解决方案

  • 首先,本身的思路是 div 以前已经绑定 mousedown 事件,再绑定 mousemove 事件,绑定事件过多从而出现快速移动失效问题。但这思路本身都感受是错的,因而网上搜索相关问题,从一篇文章中找到了其中的缘由,缘由以下:函数

    鼠标滑动地太快,天然会形成 mousemove 事件屡次发生,相应的,事件处理函数也屡次被调用,天然形成延迟。延迟以后,元素移动的速度赶不上鼠标移动的速度,可能形成鼠标移出元素的状态,从而触发了 mouseout 事件,从而形成了被拖动元素中止移动。 ——原文来自 鸢飞鱼跃

绑定到bodydocument 之间的细微差异

上面讲到,绑定 mousemove 事件到 bodydocument 上,都能拖动地很流畅,可是它们之间仍是有些细微差异的,以下图所示:测试

  • 绑定到 document
    clipboard.png
  • 绑定到 body
    clipboard.png

Chrome 测试结果中能够看到,绑定到 document 上时,鼠标移动到菜单栏上,元素依旧能被拖动,而绑定在 body 上却作不到这一点。spa

代码

最后,如下是本次测试中用到的代码,感兴趣的小伙伴能够贴下来本身跑一跑3d

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style>
        *{
            padding:0;
            margin:0;
        }
        div{
            position:absolute;
            left:100px;
            top:50px;
            width:100px;
            height:100px;
            border:1px solid #000;
        }
        body{
            width:100vw;
            height:100vh;
        }
    </style>
</head>
<body>

    <div>Drag Me</div>

    <script>
        const div = document.querySelector('div');
        const body = document.body;

        div.addEventListener('mousedown',(event) => {

            let startX = event.clientX,
            startY = event.clientY,
            left = div.offsetLeft,
            top = div.offsetTop;

            let callback = (event) => {
                const stepX = event.clientX - startX,
                stepY = event.clientY - startY;
                div.style.left = `${left + stepX}px`;
                div.style.top = `${top + stepY}px`;
            };

            document.addEventListener('mousemove',callback);

            div.addEventListener('mouseup',() => {
                document.removeEventListener('mousemove',callback);
            });

        });        
    </script>

</body>
</html>
相关文章
相关标签/搜索