Vue.directive('movable',{
bind(el){
let agent=window.navigator.userAgent.toLowerCase(),start,move,end
//判断当前是移动端还是PC,移动端监听touch,PC监听mouse
if(["android","iphone","symbianos","windows phone","ipad","ipod"].some(i=>agent.indexOf(i)>0)){ start='touchstart';move='touchmove';end='touchend' }else{ start='mousedown';move='mousemove';end='mouseup' }
//添加事件开始监听
el.addEventListener(start,e=>{
//读取事件开始时,触摸或鼠标按下的坐标,以及容器当前所在位置,并声明两个函数对象,供后面添加和取消监听用
let cur=e.touches?{x:e.touches[0].clientX,y:e.touches[0].clientY}:{x:e.clientX,y:e.clientY},x=el.offsetLeft,y=el.offsetTop,prevent=function(){event.preventDefault()},moveFun=function(){
if(event.touches){
el.style.left=event.touches[0].clientX-cur.x+x+'px'
el.style.top=event.touches[0].clientY-cur.y+y+'px'
}else{
el.style.left=event.clientX-cur.x+x+'px'
el.style.top=event.clientY-cur.y+y+'px'
}
//阻止移动端屏幕移动
window.addEventListener('touchmove',prevent,{passive:false})
}
//监听move并修改位置
el.addEventListener(move,moveFun)
//声明一个移除处理函数对象
let endFun=function(){
el.removeEventListener(move,moveFun)
el.removeEventListener(move,endFun)
window.removeEventListener('touchmove',prevent)
}
//监听到事件结束时,移除start以外的监听
el.addEventListener(end,endFun)
})
}
})
新手注意事项:
- 此处假设的是容器采用了fixed或absolute定位,然后修改left和top实现移动,如果是采用了其他定位方式需要根据实际情况做相应调整
- {passive:false}是为了让window的滑动事件能被阻止,如欲修改请注意调试是否符合实况
- 为节约资源,指令只永久监听一个start事件,其他的均在start后动态监听,由于EventListener可以重复添加,所以一轮结束后最好remove掉,此处必须用声明函数对象的方式进行增删,缘由在另一篇文章中介绍过:
Vue项目根治IOS微信web中,输入项blur之后页面不回落的问题