原生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>

在浏览器上运行结果如下

当然还可以用拖拽做一些跟有趣的事情,读者可以自行尝试。

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