Event事件学习实用路线(10)——Event事件之拖拽原理思路详解



拖拽原理思路详解




涉及事件



鼠标按下: mousedown
鼠标移动 :mousemove => 不断的改变元素的 top / left
鼠标抬起 :mouseu


原理图解



如图假如对div进行拖拽:
在这里插入图片描述
连接拖拽点
在这里插入图片描述
它的横纵坐标变化:就是增加移动的距离

在这里插入图片描述

拖拽实现



思路



  1. 保存鼠标点击的初始位置
    startPos

  2. 保存元素的初始位置
    boxPos

  3. 保存鼠标移动的位置
    nowPos

  4. 计算鼠标移动的差值
    dis

  5. 计算元素移动的距离
    newBoxPos

  6. 设置元素最终的位置
    div.style.top
    div.style.left

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置

            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);
                console.log(boxPos.x);

                div.addEventListener("mousemove", (e)=>{
                    var nowPos = {
                        x : e.clientX,
                        y : e.clientY
                    }

                    var dis = {
                        x : nowPos.x - startPos.x,
                        y : nowPos.y - startPos.y
                    }

                    var newBoxPos = {
                        left : boxPos.x + dis.x,
                        top : boxPos.y + dis.y
                    }

                    div.style.top = newBoxPos.top + 'px';
                    div.style.left = newBoxPos.left + 'px';
                });
            });
        }
    </script>
</body>
</html>

运行结果仍然存在问题:
如果鼠标拖拽过快,鼠标甩出div,而事件只能在div上,div就脱离控制了。
在这里插入图片描述
解决办法:将鼠标移动事件,添加到document上

        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置

            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);
                console.log(boxPos.x);

                document.addEventListener("mousemove", (e)=>{
                    var nowPos = {
                        x : e.clientX,
                        y : e.clientY
                    }

                    var dis = {
                        x : nowPos.x - startPos.x,
                        y : nowPos.y - startPos.y
                    }

                    var newBoxPos = {
                        left : boxPos.x + dis.x,
                        top : boxPos.y + dis.y
                    }

                    div.style.top = newBoxPos.top + 'px';
                    div.style.left = newBoxPos.left + 'px';
                });
            });
        }

但松开鼠标事件还没做,我们把它补充上。
在这里插入图片描述

注意:清除事件 - 必须清除的是命名函数!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置



            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);

                document.addEventListener("mousemove", drag);
            });

            div.addEventListener("mouseup", ()=>{
                document.removeEventListener("mousemove", drag);
            });

            function drag(e){
                var nowPos = {
                    x : e.clientX,
                    y : e.clientY
                }

                var dis = {
                    x : nowPos.x - startPos.x,
                    y : nowPos.y - startPos.y
                }

                var newBoxPos = {
                    left : boxPos.x + dis.x,
                    top : boxPos.y + dis.y
                }

                div.style.top = newBoxPos.top + 'px';
                div.style.left = newBoxPos.left + 'px';
            }
        }
    </script>
</body>
</html>

在这里插入图片描述

代码优化



清除事件应该将其代码加在mousedown中,因为逻辑上应该是鼠标按下的时候,才再加当前document的鼠标移动和抬起的两个事件。
这样避免事件加多个,引起冲突。
我们来看看鼠标清除事件执行多少遍:

        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置



            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);

                document.addEventListener("mousemove", drag);

                var i = 1;

                div.addEventListener("mouseup", ()=>{
                    console.log(i++);
                    document.removeEventListener("mousemove", drag);
                });
            });


            function drag(e){
                var nowPos = {
                    x : e.clientX,
                    y : e.clientY
                }

                var dis = {
                    x : nowPos.x - startPos.x,
                    y : nowPos.y - startPos.y
                }

                var newBoxPos = {
                    left : boxPos.x + dis.x,
                    top : boxPos.y + dis.y
                }

                div.style.top = newBoxPos.top + 'px';
                div.style.left = newBoxPos.left + 'px';
            }
        }

我们会发现移动次数越多,清除事件的执行次数就越多,原因是只要按下一次鼠标,就给div增加一个鼠标抬起事件,因此就会累加很多该事件。
在这里插入图片描述
为了提高性能:只需绑定一次清除事件。

        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置



            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);

                document.addEventListener("mousemove", drag);

                var i = 1;

                div.addEventListener("mouseup", ()=>{
                    console.log(i++);
                    document.removeEventListener("mousemove", drag);
                },{
                    // 只绑定一次事件
                    once:true
                });
            });


            function drag(e){
                var nowPos = {
                    x : e.clientX,
                    y : e.clientY
                }

                var dis = {
                    x : nowPos.x - startPos.x,
                    y : nowPos.y - startPos.y
                }

                var newBoxPos = {
                    left : boxPos.x + dis.x,
                    top : boxPos.y + dis.y
                }

                div.style.top = newBoxPos.top + 'px';
                div.style.left = newBoxPos.left + 'px';
            }
        }

现在接触绑定就只执行一次了。
在这里插入图片描述

实现限制范围的拖拽



实际拖拽过程中,放在边缘会出去一部分。
左侧的时候:left只要不是负值,div就不会出去了。
限制左侧:left不能是负值。
限制右侧:浏览器可视区宽度 - div宽度,它的left不能超过这个距离。
上下限制也同理,xiao迪就不再解释了。
在这里插入图片描述

在这里插入图片描述

        {
            let div = document.querySelector('div');

            var startPos = {} // 1. 鼠标点击的位置

            var boxPos={} // 2. 元素的初始位置



            div.addEventListener("mousedown", (e)=>{
                // 保存
                // 初始鼠标位置
                startPos.x = e.clientX;
                startPos.y = e.clientY;

                // 元素的初始位置
                boxPos.x = parseFloat(getComputedStyle(div).left);
                boxPos.y = parseFloat(getComputedStyle(div).top);

                document.addEventListener("mousemove", drag);

                var i = 1;

                div.addEventListener("mouseup", ()=>{
                    console.log(i++);
                    document.removeEventListener("mousemove", drag);
                },{
                    // 只绑定一次事件
                    once:true
                });
            });


            function drag(e){
                var nowPos = {
                    x : e.clientX,
                    y : e.clientY
                }

                var dis = {
                    x : nowPos.x - startPos.x,
                    y : nowPos.y - startPos.y
                }

                var newBoxPos = {
                    left : boxPos.x + dis.x,
                    top : boxPos.y + dis.y
                }

                // 限制左侧
                if (newBoxPos.left < 0){
                    newBoxPos.left = 0;
                }
                
                // 限制右侧
                var maxLeft = document.documentElement.clientWidth - div.offsetWidth;
                if (newBoxPos.left > maxLeft){
                    newBoxPos.left = maxLeft;
                }

                // 限制上侧
                if (newBoxPos.top < 0){
                    newBoxPos.top = 0;
                }

                // 限制下侧
                var maxTop = document.documentElement.clientHeight;
                if (newBoxPos.top > maxTop) {
                    newBoxPos.top = maxTop;
                }

                div.style.top = newBoxPos.top + 'px';
                div.style.left = newBoxPos.left + 'px';
            }
        }

在这里插入图片描述



(后续待补充)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值