vue 移动端拖放元素实现浮窗滑动效果
混合开发中,项目组需求要求每个页面上有个智能客服的入口是以浮窗的形式体现的,并且原生开发不好做,那么就有前端来实现这个需求。
需求分析:
1.每个页面都需要有浮窗存在。
2.手指滑动可以随意拖放/只能在屏幕上下拖放。
3.最好进入每个页面的时候这个浮窗的位置初始化时还在上一页面停留的位置。
4.是否存在于整个项目的最高层级。
根据需求分析,我把这个浮窗封装成一个公共的组件。
<template>
<div class="float-box" ref="floatIcon" :style="{top:floatInitTop}">
<p>浮窗的入口</p>
</div>
</template>
<script>
export default{
name:"floatIcon",
props:{},
data(){
return:{
floatInitTop:"600px"
}
},
mounted(){
this.init();
},
methods:{
init(){
let element = this.$refs.floatIcon; // 获取元素
let floatInitTop = localStorage.getItem("floatInitTop");// 获取缓存中得到Y轴的距离数据,存在数据就赋值,不存在就给一个默认的距离顶部的高度
if(floatInitTop){
this.floatInitTop = floatInitTop + "px";
}else{
this.floatInitTop = "600px";
}
let initTop = Number(floatInitTop);// 把初始高度去存一下,后面计算拖放要用到
// 下面的这些数据用于存放手指拖动的一些计算
let currentPosition = {y:0};//我这里只做了上下拖放,要做全屏的随意拖放把x相关的加进去就可以了
let offset = {};
let touchStartPosition = {};
let moveFlag = false;
element.addEventListener('touchstart',touchStart,false);
element.addEventListener('touchmove',touchMove,false);
element.addEventListener('touchend',touchEnd,false);
function touchStart(e){
let touch = e.targetTouches[0];
touchStartPosition.y = touch.pageY;
}
function touchMove(e){
moveFlag = true;
e.preventDefault();
let touch = e.targetTouches[0];
offest.y = touch.pageY - touchStartPosition.y;
move({y: currentPosition.y + offset.y});
};
function touchend(e){
if(!moveFlag) return
currentPosition.y += offset.y;
moveFlag = false;
};
function move(params){
// 计算距离顶部 / 底部的距离,然后判断Y个距离的大小
if(params.y > (document.documentElement,clientHeight - initTop) - 60){ // 60是元素本身的高度
params.y = document.documentElement,clientHeight - initTop - 60
}
if(params.y < 0 && Math.abs(params.y) > (initTop - 44)){ // 向上拉到顶之后就不要再移动了,44是我的顶部有个header的标题栏
params.y = -(initTop - 44);
}
element.style.transform = "translate(" + params.y + "px)";
localStorage.setItem('floatInitTop',element.getBoundingClientRect().top);
}
}
}
}
</script>
<style lang="less" scoped>
.float-box{
position:fixed;
right:0;
height:60;
}
</style>