之前做过元素的拖拽及数据传输,最近碰到一个在容器内拖拽移动的需求
主要是通过 mousemove 方法,监听元素的位置并赋值
首先是鼠标按下事件,鼠标按下之后,全局添加监听事件,监听鼠标的移动和鼠标的松开事件
const mousedown = (e: any, index: number) => {
e.preventDefault()
moveIndex.value = index;
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
}
鼠标移动动态赋值
const mousemove = (e: any) => {
dataList.value[moveIndex.value].x =
e.pageX - dragContainer.value.getBoundingClientRect().left >= 25
? e.pageX - dragContainer.value.getBoundingClientRect().left - 25
: 0;
dataList.value[moveIndex.value].y =
e.pageY - dragContainer.value.getBoundingClientRect().top >= 25
? e.pageY - dragContainer.value.getBoundingClientRect().top - 25
: 0;
};
鼠标松开时移除监听事件
const mouseup = () => {
moveIndex.value = null;
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
};
需要注意的是:
1. 元素距离容器的距离不能为负值(若未负值则元素会移出容器外)
2. 鼠标按下时 要加上 e.preventDefault() 阻止冒泡,当元素为图片时,不加 e.preventDefault() 会造成鼠标松开时未移除元素的移动事件 mousemove
下面是全部代码(demo只做了上和左不能移出容器的处理,下和右同理)
<template>
<div class="drag-title">元素在容器内拖拽</div>
<div class="drag-container" ref="dragContainer">
<div
class="drag-el"
v-for="(item, index) in dataList"
:key="index"
:style="{ top: item.y + 'px', left: item.x + 'px' }"
@mousedown="mousedown($event, index)"
>
{{ item.name }}
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const dragContainer = ref();
const dataList = ref([
{
name: "元素1",
x: 0,
y: 0,
},
{
name: "元素2",
x: 100,
y: 100,
},
{
name: "元素3",
x: 200,
y: 200,
},
]);
// 当前移动项
const moveIndex = ref<any>(null);
const mousedown = (e: any, index: number) => {
moveIndex.value = index;
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
};
const mousemove = (e: any) => {
dataList.value[moveIndex.value].x =
e.pageX - dragContainer.value.getBoundingClientRect().left >= 25
? e.pageX - dragContainer.value.getBoundingClientRect().left - 25
: 0;
dataList.value[moveIndex.value].y =
e.pageY - dragContainer.value.getBoundingClientRect().top >= 25
? e.pageY - dragContainer.value.getBoundingClientRect().top - 25
: 0;
};
const mouseup = () => {
moveIndex.value = null;
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
};
</script>
<style lang="less" scoped>
.drag-title {
margin: 10px 0;
text-align: center;
font-size: 18px;
font-weight: bold;
}
.drag-container {
margin: 0 auto;
width: 800px;
height: 600px;
background: skyblue;
position: relative;
.drag-el {
position: absolute;
width: 50px;
height: 50px;
background: yellowgreen;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
cursor: move;
}
}
</style>