js拖拽原理及簡單實現(渣渣自學)

jageLee發表於2020-09-10

第一步

  首先簡單分析下需求吧,我們就是想實現滑鼠拖拽帶顏色的方塊時,讓方塊停留在滑鼠鬆開的位置,需要計算的就是拖拽前的座標和拖拽後的座標,滑鼠移動後相對於原位置的偏移量=目標元素的偏移量,根據這個等式和幾個屬性實現拖拽(下面會介紹到這幾個屬性,莫急哈,後面還會遇到一個小問題,一會詳細描述),滑鼠的狀態事件有三種,滑鼠按下時的事件(mousedown),滑鼠移動時的事件(mousemove),滑鼠鬆開時的事件(mouseup)

第二部

這裡就是擼程式碼了,首先新建一個html頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #div{
        position: absolute;
        width:100px;
        height: 100px;
        background-color: deeppink;
    }
</style>
<body style="border:1px solid #000;height: 600px;margin:0">
    <div id="div"></div>
    <script>
        let tar=document.getElementById('div')
        let isDrag=false;
        tar.onmousedown=function(el){
            var el= el || event;
            isDrag=true
            if(isDrag){
                document.onmousemove=function(e){
                    var e = e || event;
                    tar.style.left= e.clientX - el.offsetX + 'px';
                    tar.style.top= e.clientY - el.offsetY + 'px';
                }
            } else {
                return
            }
            document.onmouseup=function(){
                isDrag=false;
                // tar.onmousedown=null;
                document.onmousemove=null
          document.onmouseup=null
            }
        }
        
    </script>
</body>
</html>

 

這裡時完整的程式碼,我一步一步的來解釋

(1)<body style="border:1px solid #000;height: 600px;margin:0">這段程式碼起了個初始化的作用,(因為谷歌瀏覽器會預設給body加8px的margin)border加不加無所謂,我加上是方便看一下邊界;
(2)position: absolute; 樣式中的這個東西不能缺,因為只用元素定位了之後才能使用top和left屬性;
(3)頁面中的isDrag就相當於一個開關,只有當為true的時候才允許拖拽(也就是滑鼠按下的時候才能拖拽,鬆開時isDrag自動變為false,mousemove事件就不能觸發了)
(4)var e = e || event(window.event); 這行程式碼其實也很好理解,就是為了相容,它就相當於一個函式中運用三目給e重新賦值,
(function(event){
    var e = event ? event : window.event
})()

這樣理解就簡單了,上面說了個小問題是啥,現在可以揭曉了,把頁面中的var 換成let試一下,

瀏覽器控制檯報了一行錯,如下

Uncaught SyntaxError: Identifier 'el' has already been declared

(星星個b的),咋報錯了,為啥啊,咋回事啊? 趕緊百度一下壓壓驚,

不廢話了,簡單解釋下,這裡涉及到兩個知識點:函式的形參以及let和var宣告變數的區別,函式的形參也是函式作用域的引數,也就是函式呼叫後形成的區域性作用域內的引數,它不屬於全域性哦,也就相當於使用let宣告瞭這個引數,有人會問了,用var咋就可以呢,咋就不報錯呢,因為var宣告的變數會覆蓋掉同名變數(也就是覆蓋了形參),不要槓為啥覆蓋,js就是這麼定義的,百度下答案都是大同小異,王八的屁股--龜腚(規定),

tar.style.left= e.clientX - el.offsetX + 'px';
tar.style.top= e.clientY - el.offsetY + 'px';

這兩行程式碼就是計算元素的left和top的程式碼,position天天用,top和left不難理解,e.clientX就是滑鼠終點距離div左邊的垂直距離,e.clientY就是距離div上邊的垂直距離,
el.offsetX 是div距離瀏覽器左邊的距離,el.offsetY 是距離瀏覽器頁面顯示區的距離,頁面顯示區的上邊,標籤欄下面,有一條灰邊,滑鼠動的時候這四個值也是在不斷變化的,只要設定一下div的top和left就能實現簡單的拖拽功能了
(5)mouseup事件是釋放空間,節約記憶體。
這樣就完成了一個簡單的拖拽。後面再一起學習複雜拖拽(比方說,限制範圍,拖拽生成新的等等)


document.onmouseup=null

相關文章