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';
            }
        }

在這裏插入圖片描述



(後續待補充)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章