原生JS拖拽從原理到實現

拖拽在js中挺常用的,不過目前有很多做拖拽的插件,H5也以及支持了拖拽事件,不過了解一下拖拽的原理也是有必要的,其實用原生js實現拖拽並不難。

首先講一下拖拽的原理,假設瀏覽器上有一個元素(元素已經絕對定位了),起始位置爲(mx, my),即距瀏覽器上方my px,左方mx px,如下圖

拖拽元素的過程無非就是改變該元素的left值和top值,那麼left和top值設爲多少纔對呢,其實這個不難,假設鼠標點擊元素,並設該點擊的點爲(x, y), (x, y) 肯定是在帶拖拽元素裏的,隨着鼠標的移動(是按住鼠標左右鍵的移動), 能得到新的鼠標位置,設爲(nx, ny), 此時left值應該要等於nx - x + mx, top值爲ny - y + my, 如下圖

如果看懂了上面 的內容,那麼接下來就用js實現一下,首先需要關注三個事件,mousedown: 鼠標按下事件,mousemove: 鼠標移動事件,mouseup: 鼠標鬆開事件。對於元素的初始位置(mx, my)我們這裏使用element.offsetLeft和element.offsetTop來獲取,鼠標按下的位置(x, y)我們可以使用event.clientX, event.clientY來獲取。實現代碼如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    html, body {
        height: 100%;
    }
    * {
        margin: 0;
        padding: 0;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
    }
    #target {
        width: 100px;
        height: 100px;
        background: blueviolet;
        border-radius: 50%;
        box-shadow: 0 0 5px rgba(0,0,0,.02);
        position: absolute; /*元素記得絕對定位*/
        left: 10px;
        top: 10px;
    }
</style>
<body>
<div id="target">

</div>
<script>
    !function (window, document) {   
        //工具函數的封裝
        var getById = document.getElementById.bind(document);
        
        var getStyle = function () {
            return window.getComputedStyle ? function (element, style) {
                return window.getComputedStyle(element)[style]
            } : function (element, style) {
                return element.currentStyle[style]
            }
        }();
        
        var addEvent = function () {
            return document.addEventListener ? function (element, eventType, callback) {
                element.addEventListener(eventType, callback, false)
            } : document.attachEvent ? function (element, eventType, callback) {
                element.attachEvent("on" + eventType, callback)
            } : function (element, eventType, callback) {
                element["on" + eventType] = callback
            }
        }();

        function setStyle(element, css) {
            for (var k in css) {
                if (css.hasOwnProperty(k)) {
                    element.style[k] = css[k]
                }
            }
        }

        var target = getById("target"); // 獲取元素
        var x, y, mx, my, dx, dy, drag = false; // 需要設置一個drag來標記是否拖拽
        addEvent(target, "mousedown", function (e) { // mousedown事件
            e = e || window.event;
            drag = true;
            x = e.clientX;
            y = e.clientY;
            mx = this.offsetLeft;
            my = this.offsetTop;
            dx = x - mx;
            dy = y - my;
        });
        addEvent(document, "mousemove", function (e) { // mousemove事件, 綁在document上比較好一點
            e = e || window.event;
            if (!drag) return false;  
            var left = e.clientX - dx, // left = nx - (x - mx)
                top = e.clientY - dy;  // top = ny - (y - my)
            setStyle(target, {left: left + "px", top: top + "px"});
        });
        addEvent(target, "mouseup", function (e) { // mouseup鼠標鬆開
            drag = false
        });
    }(this, document);
</script>
</body>
</html>

在瀏覽器上運行結果如下

當然還可以用拖拽做一些跟有趣的事情,讀者可以自行嘗試。

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