Javascript 简单的拖拽效果实现

631 阅读2分钟

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

Javascript 简单的拖拽效果实现

之前面试的时候有被问到实现一个拖拽组件的思路。当时比较迷,就算是伪代码感觉也说话不太清楚,一个可能是相关的api记不清楚,然后也确实没有思考过这个场景。这篇文章主要是记录一个简单的拖拽效果的实现。

先来想一想要实现拖拽的效果可以拆分为哪些点

  • 获取拖拽的元素
  • 关于元素位置的操作,如何表示,如何获取,如何计算偏移量,如何计算新值等
  • 表示拖拽动作,包括拖拽开始和结束,如何设置对应的回调函数。
  • 如何判断拖拽的边界

思路:

  • 关于元素的位置,可以将元素设置为绝对定位,通过top和left值来表示元素的位置。
  • 鼠标的位置可以通过clientXclientY属性来获取
  • 拖拽元素的偏移量(移动距离)可以表示为鼠标当前与可视区边界的距离-鼠标与拖拽元素的距离,计算出新的位置。
//鼠标与拖拽元素的距离=鼠标与可视区边界的距离-拖拽元素与可视区的距离 
let diffX = e.clientX - drag.offsetLeft; 
let diffY = e.clientY - drag.offsetTop;
//拖拽元素的移动距离=鼠标当前与可视区边界的距离-鼠标与拖拽元素的距离 
let left = e.clientX - diffX; 
let top = e.clientY - diffY;
  • 关于如何表示拖拽动作。可以通过onmousemoveonmouseup两个事件来表示拖拽过程中的动作。分别在onmousemove中重新计算和设置元素的位置。在onmouseup中取消事件的监听。

  • 如何判断拖拽的边界这点,可以通过 window.innerWidthdrag.offsetWidth 这两个属性来判断。如果左偏移量超出了window.innerWidth - drag.offsetWidth,则重新设置为window.innerWidth - drag.offsetWidth

if (left > window.innerWidth - drag.offsetWidth) {
    //超出了就放在innerWidth的位置
    left = window.innerWidth - drag.offsetWidth;
}

完整的代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box{
            width: 100px;
            height: 100px;
            background-color: aqua;
            position: absolute;
        }
    </style>
</head>

<body>
    <div id="box"></div>
    <script>
        window.onload = function () {
            //drag目标是绝对定位状态
            var drag = document.getElementById('box');
            drag.onmousedown = function (e) {
                console.log("Aaa")
                e = e || window.event;
                //鼠标与拖拽元素的距离=鼠标与可视区边界的距离-拖拽元素与可视区的距离
                let diffX = e.clientX - drag.offsetLeft;
                let diffY = e.clientY - drag.offsetTop;
                drag.onmousemove = function (e) {
                    console.log("bbb")
                    e = e || window.event;
                    //拖拽元素的移动距离=鼠标当前与可视区边界的距离-鼠标与拖拽元素的距离
                    let left = e.clientX - diffX;
                    let top = e.clientY - diffY;
                    //避免拖出可视区外
                    if (left < 0) { left = 0; }
                    else if (left > window.innerWidth - drag.offsetWidth) {
                        //超出了就放在innerWidth的位置
                        left = window.innerWidth - drag.offsetWidth;
                    }
                    if (top < 0) top = 0;
                    else if (top > window.innerHeight - drag.offsetHeight) {
                        top = window, innerHeight - drag.offsetHeight;
                    }
                    drag.style.left = left + 'px';
                    drag.style.top = top + 'px';
                }
                drag.onmouseup = function (e) {
                    e = e || window.event;
                    // this.onmousemove = null;
                    // this.onmousedown = null;
                }
            }
        }
    </script>
</body>

</html>

更新:写完突然发现HTML5中好像有专门的拖拽api,了解之后再新写一篇文章好了哈哈哈