START
- 番茄我又又又来写点啥了,最近被需求折磨的不要不要的,要做一个在线PPT做的网站。元素拖动算是其中一小部分的功能吧,但是还是出了很多的bug,这篇文章算是我对元素拖拽相关的记录吧。
- 仅以此文记录自己寻找问题花费的3小时。
元素拖动
- 话不多说先上代码,后面再一个一个解释
<template>
<div class="move">
<h2>vue中元素拖动一</h2>
<div class="all">
<div
class="item"
@mousedown.stop="move($event)"
:style="{ left: sonLeft+'px', top: sonTop+'px' }"
></div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sonLeft: 10,
sonTop: 20,
};
},
methods: {
// 元素拖动事件
move(e) {
let element = e.currentTarget;
//算出鼠标相对元素的位置
let disX = e.clientX - element.offsetLeft;
let disY = e.clientY - element.offsetTop;
document.onmousemove = (e) => {
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//移动当前元素
this.sonLeft = left;
this.sonTop = top;
};
document.onmouseup = (e) => {
//鼠标弹起来的时候不再移动
document.onmousemove = null;
//预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
document.onmouseup = null;
};
},
},
};
</script>
<style scoped>
.all {
position: relative;
width: 1000px;
height: 700px;
background-color: pink;
}
.item {
position: absolute;
left: 10px;
top: 20px;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
- 简单说一下逻辑,给需要拖动的元素绑定left,top属性
- 给需要拖动的元素绑定事件,根据鼠标的移动,修改对应元素的left,top变量
- 难点就是 e.clientX ;e.clientY ;element.offsetTop;element.offsetLeft;这几个属性指的是什么,为什么这样就可以实现元素的拖动,画个图,很好理解,请看下图
![](https://img.haomeiwen.com/i13278218/3afaf66e9657f66b.jpg)
- 如果上图不好理解,简单的说就是 鼠标相对于之前挪动了
S
,S
加上元素原本的偏移量,就是元素挪动之后的偏移量。
若上一级定位元素缩放了怎么做拖拽
- 由于是在线ppt的需求,所以定位元素的大小是自适应的,会发生缩放,所以对应的left,top要响应的改变
- 话不多说直接上代码
<template>
<div class="move">
<h2>vue中元素拖动二</h2>
<div class="all">
<div
class="item"
@mousedown.stop="move($event)"
:style="{ left: sonLeft + 'px', top: sonTop + 'px' }"
>
left: {{ sonLeft }}
<br />
top{{ sonTop }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sonLeft: 20,
sonTop: 10,
};
},
methods: {
// 元素拖动事件
move(e) {
let element = e.currentTarget;
//算出鼠标相对元素的位置
let disX = e.clientX - element.offsetLeft * 0.6;
let disY = e.clientY - element.offsetTop * 0.6;
document.onmousemove = (e) => {
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//移动当前元素
this.sonLeft = left / 0.6;
this.sonTop = top / 0.6;
};
document.onmouseup = (e) => {
//鼠标弹起来的时候不再移动
document.onmousemove = null;
//预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
document.onmouseup = null;
};
},
},
};
</script>
<style scoped>
.all {
position: relative;
width: 1000px;
height: 700px;
background-color: pink;
transform: scale(0.6, 0.6);
transform-origin: 0% 0%;
}
.item {
position: absolute;
left: 10px;
top: 20px;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
啰嗦一句,上述代码的0.6就是缩放比例,由于比较懒,没有改,应该是用变量去控制相对来说好很多。
至于怎么在vue中变量绑定transform: scale(0.6, 0.6);看下面的链接文章
还未解决的问题
- 先上代码
<template>
<div class="move">
<h2 @click="add">vue中元素拖动三</h2>
<div class="all">
<div
class="item"
v-for="(item, index) in list"
:key="item.name"
:style="{ left: item.sleft + 'px', top: item.stop + 'px' }"
@mousedown.stop="move(index, $event)"
>
<img :src="item.url" alt="" style="width: 100%; height: 100%" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sonLeft: 0,
sonTop: 0,
list: [
{
name: "1",
sleft: 20,
stop: 30,
url:
"https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
},
{
name: "2",
sleft: 200,
stop: 300,
url:
"https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
},
{
name: "3",
sleft: 400,
stop: 600,
url:
"https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
},
],
};
},
methods: {
// 元素拖动事件
move(index, e) {
let element = e.currentTarget;
console.log(e.currentTarget);
// 阻止默认的图片拖拽事件
e.preventDefault();
//算出鼠标相对元素的位置
let disX = e.clientX - element.offsetLeft * 0.6;
let disY = e.clientY - element.offsetTop * 0.6;
document.onmousemove = (e) => {
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//移动当前元素
this.list[index]["sleft"] = left / 0.6;
this.list[index]["stop"] = top / 0.6;
};
document.onmouseup = (e) => {
//鼠标弹起来的时候不再移动
document.onmousemove = null;
//预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
document.onmouseup = null;
};
},
add() {
console.log("添加元素");
this.list.push({
name: "4",
url:
"https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
});
},
},
};
</script>
<style scoped>
.all {
position: relative;
width: 1000px;
height: 1000px;
background-color: pink;
transform: scale(0.6, 0.6);
transform-origin: 0% 0%;
}
.item {
position: absolute;
left: 0px;
top: 0px;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
描述
- 我写了一个demo
- vue下 一个图片列表
- 然后绑定变量到样式的top left 实现位置的控制
- 添加一个点击事件 然后往展示的list数组里面添加一个对象
- 但是这个对象没有加 top left 属性(原本list中的对象都有这两个属性)
- 然后给这些图片列表添加了元素拖动的事件
- 数组中有left top属性的元素拖拽 很流畅
- 但是新添加的对象,因为没有 加left top 拖动特别卡顿
- 还不清楚原因。。能解决的私聊我,发红包。
END
整体的元素拖拽其实理解清楚对应的属性,理解计算的方法很好理解的,整体来说不难,后面的问题,暂时能力有限,先记录一下吧。后期能解决了,定会补充。时间匆忙,命名不规范见谅。
网友评论