一、效果如下:
二、思路和步骤:
整体思路是在鼠标按下时计算初始偏移值,并在拖拽过程中更新 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>