实现对div的拖动功能,需要先要知道以下的一些原生事件和方法;
1,事件:
方法 | 描述 |
---|---|
onmousedown | 鼠标按钮被按下 |
onmousemove | 鼠标被移动 |
onmouseup | 鼠标按键被松开 |
2,方法:
方法 | 描述 |
---|---|
event.clientX | 返回当事件被触发时鼠标指针相对于浏览器页面(或窗口)的水平坐标 |
event.clientY | 同上,返回的是垂直坐标 |
event.offsetLeft | 只读属性,返回当前元素左边框距定位元素(或者最近的元素) 左侧的像素值 |
event.offsetTop | 只读属性,返回当前元素上边框距定位元素(或者最近的元素) 顶部的像素值 |
event.clientHeight | 只读属性,返回该元素的像素高度,高度包含内边距(padding),不包含边框(border),外边距(margin)和滚动条,是一个整数,单位是像素 px |
event.clientWidth | 同上,返回该元素的像素宽度 |
event.offsetHeight | 只读属性,它返回该元素的像素高度,高度包含内边距(padding)和边框(border),不包含外边距(margin),是一个整数,单位是像素 px |
event.offsetWidth | 同上,返回该元素的像素宽度 |
注意:clientHeight ,clientWidth 和 offsetHeight offsetWidth 获取元素高度宽度的尺寸不太一样,我这边使用的的 offsetHeight offsetWidth;
图例说明:
实现的效果图如下:
3,实现如下:
重要说明:
1,mousedown()
鼠标按下时需要计算位置差,因为clientX和offsetLeft的属性返回的位置不一样 要相减得到鼠标在拖动元素内实际点击的位置, 后面每一次拖动时都要减去这个差值 否则就会造成你拖动的位置一直都是元素的左上角 而不是你之前点击的位置;
2,onmousemove ()
鼠标移动事件和onmouseup
鼠标抬起事件要添加到 document 元素上面,因为在拖动的过程中如果拖动过快,鼠标移出了拖动元素,导致拖动元素丢失了移动事件;
3,拖动限制范围的判断建议使用第二种方法,第一种我这边演示的时候发现div靠边时经常会有间隙,不太流畅;
4,onmouseup
鼠标抬起时需要解绑鼠标移动事件;
drag.vue
<template>
<div class="dragContainerEl">
<div id="Drag" @mousedown="mousedown($event)" class="drag"></div>
</div>
</template>
<script>
export default {
name: "dragContainerEl",
data() {
return {
DragEl: null,//拖动元素
dragContainerEl: null,//容器元素
// 位置差
disX: 0,
disY: 0,
// 元素未拖动时的初始位置 绑定的是行内样式
styleObj: {
left: 0,
top: 0
}
};
},
mounted() {
this.DragEl = document.getElementById("Drag");
this.dragContainerEl = document.getElementsByClassName("dragContainerEl")[0];
},
methods: {
/* 鼠标按下 */
mousedown(event) {
// 1,计算位置差
// 因为clientX和offsetLeft的属性返回的位置不一样 要相减得到鼠标在拖动元素内实际点击的位置
// 后面每一次拖动时都要减去这个差值 否则就会造成你拖动的位置一直都是元素的左上角 而不是你之前点击的位置
this.disX = event.clientX - this.DragEl.offsetLeft;
this.disY = event.clientY - this.DragEl.offsetTop;
//2, 获取拖动元素的高度和容器的高度 为了下面进行限制元素拖动的范围
let dragHeight = this.DragEl.offsetHeight;
let dragWidth = this.DragEl.offsetWidth;
let dragContainerWidth = this.dragContainerEl.offsetWidth; //获取容器的高度和宽度
let dragContainerHeight = this.dragContainerEl.offsetHeight;
// 添加鼠标移动事件
document.onmousemove = (el) => {
// 3,获取鼠标移动位置
let moveX = el.clientX - this.disX;
let moveY = el.clientY - this.disY;
// 4,限制拖动
//控制范围:在元素 被拖拽的过程中 判断 元素的定位值 是否到达边界 如果到了 就不能在走了
4.1第一种 限制范围的判断
// if(moveX <=0 || moveY <=0){ // 控制上边界和左边界
// return
// }
// if(moveX >= dragContainerWidth - dragWidth || moveY >= dragContainerHeight - dragHeight){
// return
// }
4.2 第二种限制方位的判断 建议使用第二种; 第一种靠边时经常会有边距,不太丝滑
// 左边界
if (moveX <= 0) {
moveX = 0;
}
// 上边界
if (moveY <= 0) {
moveY = 0;
}
//下边界 容器高度 - 拖动元素高度
if (moveY >= dragContainerHeight - dragHeight) {
moveY = dragContainerHeight - dragHeight;
}
//右边界 容器宽度 - 拖动元素宽度
if (moveX >= dragContainerWidth - dragWidth) {
moveX = dragContainerWidth - dragWidth;
}
// 5, 开始移动
this.DragEl.style.left = moveX + "px";
this.DragEl.style.top = moveY + "px";
};
/* 6,鼠标抬起解除事件 */
document.onmouseup = () => {
document.onmousemove = null;
};
}
}
};
</script>
<style scoped lang="scss">
.dragContainerEl {
position: relative;
width: 100%;
height: 100%;
border: 1px solid red;
}
.drag {
position: absolute;
width: 50px;
height: 50px;
border: 5px solid yellowgreen;
background-color: red;
text-align: center;
}
</style>