H5上经常会有这样的需求,有一个悬浮的图标,常常需要在拖动时,拖拽到移动的位置。
/**
* 核心思想为动态改变Dom节点的left与top
* 1、创建Dom节点,节点动态绑定left、top;
* 2、页面构建时,获取屏幕宽度、高度,通过计算赋予Dom节点初始化的left,top;
* 3、监听touchstart,当移动开始时,清除之前的动画;
* 4、监听touchmove,移动过程中,获取事件对象中touch[0]的clientX、clientY,此为当前touch的x、y坐标,减去Dom节点自身宽高的一半,进行left、top的赋值;
* 5、监听touchend,做相应的业务操作,譬如赋值拖动的动画等;
*/
Dom节点
<div class="point" ref="point" :style="`width:${divWidth}px;height:${divHeight}px;left:${moveLeft}px;top:${moveTop}px;`"
@touchstart.prevent="(e)=>{dragStart(e)}"
@touchend.prevent="(e)=>{dragEnd(e)}"
@touchmove.prevent="(e) => dragMove(e)"
>
</div>
css
.out {//最外层div
height: 100%;
position: relative;
}
.point{
background-color: #ffb403;
border-radius: 50%;
position: absolute;
}
Vue-js
export default {
data () {
return {
border_distance:10,//可拖拽元素距离屏幕边界最小距离
divWidth:30,//可拖拽元素宽度
divHeight:30,//可拖拽元素高度
moveLeft:0,//可拖拽元素距离屏幕左边界
moveTop:0,//可拖拽元素距离屏幕上边界
clientWidth:0,//屏幕宽度
clientHeight:0//屏幕高度
}
}
}
methods:{
dragStart(e){
this.$refs.point.style.transition="none";
},
dragEnd(e){
this.$refs.point.style.transition = 'all 0.3s';
if(this.moveLeft > this.clientWidth/2){//若移动位于屏幕的左边或右边,则自动贴合左边或右边(此根据业务具体需求表现而定)
this.moveLeft = this.clientWidth - this.divWidth - this.border_distance;
}else{
this.moveLeft = this.border_distance;
}
},
dragMove(e){
if(e.touches.length){
let touch = e.touches[0];
this.moveLeft = touch.clientX - this.divWidth/2;//因拖动的中间点为Dom节点的中心点,所以left需减去Dom节点一半的宽度
this.moveTop = touch.clientY - this.divHeight/2;//top原理同上
}
}
}