一、效果如下:

二、思路和步骤:

整体思路是在鼠标按下时计算初始偏移值,并在拖拽过程中更新 div 元素的位置,通过事件监听器实现拖拽效果。

(1)用户点击触发拖拽:

当用户点击可拖拽的 div 元素时,通过 mousedown 事件触发 startDrag 函数。

(2)初始化变量:

startDrag 函数初始化一些变量,包括水平和垂直方向上的偏移值,以及拖拽状态。

(3)引入倍率调整偏移值:

在鼠标按下瞬间,通过计算初始偏移值时引入了一个倍率 offsetMultiplier,用于调整 div 与鼠标的距离。通过调整这个常量,可以控制 div 距离鼠标的远近。

(4)添加事件监听器:

函数添加移动事件和鼠标松开事件的监听器,以便在拖拽过程中实时更新 div 的位置。

(5)移动事件处理:

在移动事件处理函数 moveHandler 中,计算新的位置,并在检查新位置是否在视口内后,更新 div 元素的 left 和 top 样式,实现拖拽效果。

(6)边界检查:

为了确保拖拽过程中不会超出视口范围,进行了边界检查。

(7)鼠标松开处理:

鼠标松开事件处理函数 upHandler 主要用于在鼠标松开时停止拖拽,将拖拽状态重置,并移除事件监听器。

(8)模板中绑定事件:

在模板中绑定 mousedown 事件,实现了在点击 div 元素时触发拖拽效果。

(9)样式定义:

在样式中,定义了 div 的基本样式,包括绝对定位、鼠标样式等。

三、源码如下:

<template>
    <div class="drag_wrap">
        <p>分页组件实现拖拽功能</p>
        <!-- 可拖拽的 div -->
        <div ref="draggableDiv" class="draggable" @mousedown="startDrag">
            <el-pagination layout="prev, pager, next" :total="50" />
        </div>
    </div>
</template>
<script setup>
// 初始化可拖拽的 div 的引用
const draggableDiv = ref(null);
// 处理开始拖拽的函数
const startDrag = (event) => {
    // 初始化偏移值和拖拽状态
    let offsetX, offsetY, isDragging = false;
    // 偏移值的倍率,用于调整 div 与鼠标的距离
    const offsetMultiplier = -1.2; // 调整这个常量以改变偏移量
    //offsetMultiplier 是一个常量,你可以根据需要调整它的值。增大这个常量会使 div 更靠近鼠标,而减小它会让 div 离鼠标更远,根据实际情况进行调整
    // 计算初始偏移值
    offsetX = event.clientX - draggableDiv.value.getBoundingClientRect().left - draggableDiv.value.clientWidth * offsetMultiplier;
    offsetY = event.clientY - draggableDiv.value.getBoundingClientRect().top - draggableDiv.value.clientHeight * offsetMultiplier;
    // 处理移动事件的函数
    const moveHandler = (e) => {
        if (!isDragging) return;
        // 计算新的位置
        const x = e.clientX - offsetX;
        const y = e.clientY - offsetY;
        // 检查新位置是否在视口内
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        if (x >= 0 && x + draggableDiv.value.clientWidth <= viewportWidth) {
            draggableDiv.value.style.left = `${x}px`;
        }
        if (y >= 0 && y + draggableDiv.value.clientHeight <= viewportHeight) {
            draggableDiv.value.style.top = `${y}px`;
        }
    };
    // 处理鼠标松开事件的函数
    const upHandler = () => {
        isDragging = false;
        draggableDiv.value.style.cursor = 'grab';
        document.removeEventListener('mousemove', moveHandler);
        document.removeEventListener('mouseup', upHandler);
    };
     // 设置拖拽状态和鼠标样式 将拖拽状态重置
    isDragging = true;
    draggableDiv.value.style.cursor = 'grabbing';
    // 监听移动和松开事件
    document.addEventListener('mousemove', moveHandler);
    document.addEventListener('mouseup', upHandler);
};
</script>
  
<style lang="scss" scoped>
.drag_wrap {
    padding: 50px;
    .draggable {
        position: absolute;
        cursor: grab;
        user-select: none;
        background-image: linear-gradient(25deg, #8e84cf, #8f9cb9, #8ab3a2, #7fca89);
        color: #fff;
        padding: 10px;
        :deep(.el-pager li ) {
            margin-right: 10px;
        }
        :deep(.el-pagination>.is-first) {
            margin-right: 10px;
        }
    }
}
</style>

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐