手写拖拽定位

398 阅读2分钟

经上一篇拖拽排序的启发,本篇手写一个拖拽定位。

在工作中经常会遇到需要在页面上写悬浮按钮,但是位置固定的话总会遮挡页面,所以本篇实现允许将悬浮按钮拖拽到指定位置,就像这样。

屏幕录制2022-11-18_23_02_05_AdobeExpress.gif

HTML&CSS

html和css部分很简单,就是在页面上画一个悬浮按钮

.drag {
    position: fixed;
    top: 20px;
    left: 300px;
    width: 50px;
    object-fit: cover;
}
<body>
    <img src="https://mainaer-img.oss-cn-hangzhou.aliyuncs.com/mainaer-EIM/logo.png" class="drag"></img>
</body>

按下鼠标或者触控板(mousedown

mousedown 事件在指针设备按钮按下时触发。

在鼠标按下时记录指针与悬浮按钮的边距的偏移量,left值就等于指针x轴坐标减去左边的偏移量,top值就等于指针y轴坐标减去顶部的偏移量,如图所示:

position.png

const drag = document.querySelector('.drag');
let dragging = false, offsetLeft = 0, offsetTop = 0;
drag.onmousedown = (e) => {
    e.preventDefault();
    const { left, top } = drag.getBoundingClientRect(); // 获取悬浮按钮当前的top值和left值
    drag.classList.remove('transition-left'); // 移除过渡效果
    offsetLeft = e.clientX - left; // 点击的x轴坐标距悬浮按钮左边的距离
    offsetTop = e.clientY - top; // 点击的y轴坐标距悬浮按钮顶部的距离
    dragging = true; // 拖动状态
};

开始拖动(mousemove

当指针设备 ( 通常指鼠标 ) 在元素上移动时,mousemove 事件被触发。

在拖动时,实时计算left值和top值,且两个值的大小都在0-max这个区间内

document.onmousemove = (e) => {
    e.preventDefault();
    if(dragging) { // 只在拖动状态下处理
        // 获取悬浮按钮的节点信息
        const { left, top, width, height } = drag.getBoundingClientRect();
        // 可拖动的最大值,即悬浮按钮在右下角时的top值和left值
        const maxLeft = window.innerWidth - width, maxTop = window.innerHeight - height; 
        // 设置left值
        if(left >= 0 && left <= maxLeft) drag.style.left = countPosition(e.clientX, offsetLeft, maxLeft) + 'px';
        // 设置top值
        if(top >= 0 && top <= maxTop) drag.style.top = countPosition(e.clientY, offsetTop, maxTop) + 'px';
    }
};
// 计算当前的left值或者top值,在0 - max之间
function countPosition(clientSize, offsetSize, maxSize) {
    const value = clientSize - offsetSize
    if(value < 0) {
        return 0;
    } else if(value >= 0 && value <= maxSize) {
        return value;
    } else {
        return maxSize;
    }
};

松开鼠标或者触控板(mouseup

当指针在元素中时, mouseup事件在指针设备(如鼠标或触摸板)按钮放开时触发。mouseup 事件与mousedown事件相反。

在结束拖动时,根据当前悬浮按钮的位置自动回退到窗口左边或者右边

document.onmouseup = (e) => {
    e.preventDefault();
    dragging = false; // 取消拖动态
    drag.classList.add('transition-left'); // 添加过渡效果
    const {left, width} = drag.getBoundingClientRect();
    // 当此时的悬浮按钮在左半屏的时候,自动回退到左边
    if((window.innerWidth - width) / 2 >= left) {
        drag.style.left = '10px';
    } else {
        // 自动回退到右边
        drag.style.left = window.innerWidth - width - 10 + 'px';
    }
};
// 过渡效果
.transition-left {
    transition: left .5s;
}

至此,拖动定位的效果就实现了。

前端小渣渣的学习总结,如有错误,欢迎指正!!