拖拽

401 阅读1分钟

image.png

offsetLeft与offsetTop获取当前元素距离其父级参照物(position定位时的参照物)偏移值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
            position: absolute;
            left: 0;
            top: 0;
            background-color: yellow;
            cursor: move;
        }
    </style>
</head>

<body>
    <div class="box" id="box"></div>
    <!-- 只要鼠标在盒子滑动就触发move -->
    <script>
        let box = document.getElementById('box');
        box.addEventListener("mousedown", down)
            // 
        function down(ev) {
            this.startX = ev.clientX;
            this.startY = ev.clientY;
            this.startL = this.offsetLeft;
            this.startT = this.offsetTop;
            this.addEventListener('mousemove', move)
            this.addEventListener('mouseup', up)
        }

        function move(ev) {
            let curL = ev.clientX - this.startX + this.startL;
            let curT = ev.clientY - this.startY + this.startT;
            this.style.cssText = `left:${curL}px;top:${curT}px`
        }

        function up(ev) {
            this.removeEventListener('mousemove', move)
            this.removeEventListener('mouseup', up)
        }
        // 鼠标移动太快,鼠标会脱离盒子
        // 鼠标移动过快,鼠标会脱离拖拽的盒子,在盒子外面移动无法触发盒子的mousemove,
        // 盒子不会跟着计算最新的位置
        // 在盒子外面松开鼠标,也不会触发盒子的mouseup,导致mousemove无法移除,当鼠标
        // 重新进入盒子不论是否按住,盒子都会跟着走

    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
            position: absolute;
            left: 0;
            top: 0;
            background-color: yellow;
            cursor: move;
        }
    </style>
</head>

<body>
    <div class="box" id="box"></div>
    <!-- 只要鼠标在盒子滑动就触发move -->
    <script>
        // 解决
        //  * [IE和火狐浏览器中]
        //  * setCapture / releaseCapture:可以实现把元数和鼠标绑定在一起(或者移除绑定)
        //  的效果,来防止鼠标焦点丢失
        // [谷歌中的解决方案]
        // 孙猴子(鼠标)蹦的在欢快,也逃离不了如来佛祖(document)的五指山,
        // 所以我们在项目中,move和up方法绑定给document,而不是盒子
        let box = document.getElementById('box');
        box.addEventListener("mousedown", down)
            // 
        function down(ev) {
            this.startX = ev.clientX;
            this.startY = ev.clientY;
            this.startL = this.offsetLeft;
            this.startT = this.offsetTop;
            // this.addEventListener('mousemove', move)              
            // this.addEventListener('mouseup', up)
            this._MOVE = move.bind(this);
            this._UP = up.bind(this);
            document.addEventListener('mousemove', this._MOVE)
            document.addEventListener('mouseup', this._UP)
                // 这样处理后move/up的this是document(但是我们需要保证this是盒子),move.bind()返回的是代理函数
                // 以后移除的也是代理函数才行 每bind一次都返回一个新的代理函数
                // this.setCapture
        }

        function move(ev) {
            let curL = ev.clientX - this.startX + this.startL;
            let curT = ev.clientY - this.startY + this.startT;
            // this.style.cssText = `left:${curL}px;top:${curT}px`
            this.style.left = curL + 'px'
            this.style.top = curT + 'px'
        }

        function up(ev) {
            document.removeEventListener('mousemove', this._MOVE)
            document.removeEventListener('mouseup', this._UP)
                // this.releaseCapture
        }
    </script>
</body>

</html>