思路:
1、把要拖动的元素进行相对定位,通过改变定位的px数值来实现拖动效果。
2、通过移动端手指触摸屏幕事件来计算px的值。
实现步骤:
方法一:全局封装
1、建个js文件,将方法封装成vue自定义指令
import Vue from 'vue';
// 1.参数一:指令的名称,定义时指令前面不需要写v-
// 2.参数二:是一个对象,该对象中有相关的操作函数
// 3.在调用的时候必须写v-
const drag = Vue.directive('drag', {
// 2.每个
// inserted表示一个元素,插入到DOM中会执行inserted函数,只触发一次,
// 函数中第一个参数永远是el,表示绑定指令的元素,el参数是原生js对象
// 注意:通过el.focus()是无法获取焦点的,因为只有插入DOM后才生效
inserted: function (el) {
// 1.开会触摸屏幕
el.ontouchstart = function (e) {
let disx = e.targetTouches[0].pageX - el.offsetLeft;
let disy = e.targetTouches[0].pageY - el.offsetTop;
let maxTop = document.body.clientHeight - el.offsetHeight
let maxLeft = document.body.clientWidth - el.offsetWidth
// 2.手指持续移动
document.ontouchmove = function (e) {
let left = e.targetTouches[0].pageX - disx
let top = e.targetTouches[0].pageY - disy
// 设置上下左右边界
if (top <= 0) {
top = 0
} else if (top > maxTop) {
top = `${maxTop}px`
}else {
top = `${top}px`
}
if (left <= 0) {
left = 0
} else if (left > maxLeft) {
left = `${maxLeft}px`
}else {
left = `${left}px`
}
el.style.top = top
el.style.left = left
}
// 3.手指离开屏幕
document.ontouchend = function (e) {
// 这里必须要清除,否则点击别的元素也会触发拖动
document.ontouchmove = document.ontouchend = null;
}
}
}
})
export default drag;
2、在要使用的vue文件内引用封装的js文件,并给要拖动的元素添加自定义指令即可
<template>
<!-- 拖拽元素 -->
<div class="goinvoice" >
<div class="main" v-drag ></div>
</div>
</template>
<script>
import drag from './drag'
export default {}
</script>
<style>
.goinvoice {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
}
.main {
width: 100px;
height: 100px;
background: white;
position: absolute;
top: 28%;
left: 50%;
z-index: 101;
padding: 10px;
border-radius: 2px;
}
</style>
方法二:组件内封装(可用于有eslint校验的项目)
1、封装
export default {
directives: {
drag: {
inserted: function (el) {
// 1.开会触摸屏幕
el.ontouchstart = function (e) {
let disx = e.targetTouches[0].pageX - el.offsetLeft
let disy = e.targetTouches[0].pageY - el.offsetTop
let maxTop = document.body.clientHeight - el.offsetHeight
let maxLeft = document.body.clientWidth - el.offsetWidth
// 2.手指持续移动
document.ontouchmove = function (e) {
let left = e.targetTouches[0].pageX - disx
let top = e.targetTouches[0].pageY - disy
// 设置上下左右边界
if (top <= 0) {
top = 0
} else if (top > maxTop) {
top = `${maxTop}px`
} else {
top = `${top}px`
}
if (left <= 0) {
left = 0
} else if (left > maxLeft) {
left = `${maxLeft}px`
} else {
left = `${left}px`
}
el.style.top = top
el.style.left = left
}
// 3.手指离开屏幕
document.ontouchend = function (e) {
// 这里必须要清除,否则点击别的元素也会触发拖动
document.ontouchmove = document.ontouchend = null
}
}
}
}
},
}
2、使用
<template>
<!-- 拖拽元素 -->
<div class="goinvoice" >
<div class="main" v-drag ></div>
</div>
</template>
<style>
.goinvoice {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
}
.main {
width: 100px;
height: 100px;
background: white;
position: absolute;
top: 28%;
left: 50%;
z-index: 101;
padding: 10px;
border-radius: 2px;
}
</style>
注意:
pc端只需要把手指触摸屏幕的三个事件改成鼠标对应的三个事件,pageX 、pageY的获取方式也改一下即可e.pageX
。