手动实现自定义手势
首页 专栏 javascript 文章详情
0

手动实现自定义手势

user_QMCj0o9d 发布于 2 月 25 日

自定义手势判断在日历上的应用

在移动端,通常日历展示为当前月的日期纪录,当切换月份的过程中,需要通过手势左滑或者右滑进行月份切换,以下说明如何自行完成一个滑动的手势判断以及逻辑处理

这里借助Vue的自定义指令进行代码阐述,SELECTWRAP_DOM为绑定的DOM元素

bind(el, binding, vnode) {
 var startX = 0
 var startY = 0
 var endX = 0
 var endY = 0
 const SELECTWRAP_DOM = el
 var judgeX = 0
 var judgeY = 0
 var lockY = false
 SELECTWRAP_DOM.addEventListener('touchstart', (event) => {
 // 监听滑动开始,细节见下方
 }
 SELECTWRAP_DOM.addEventListener('touchmove', (event) => {
 // 监听滑动,细节见下方
 }
 SELECTWRAP_DOM.addEventListener('touchend', (event) => {
 // 监听滑动结束,细节见下方
 }
}
首先获取到dom元素之后,对其绑定touchstart事件,也就作为手势判断的起点
SELECTWRAP_DOM.addEventListener('touchstart', (event) => {
     var touch = event.touches[0]
     // 获取当前触控点起点的坐标,包含X,Y
     startX = touch.pageX
     startY = touch.pageY
    })
然后对dom监听touchmove事件,但是此事件只获取起始的第一个点,作为手势判断的终点
SELECTWRAP_DOM.addEventListener('touchmove', (event) => {
     var touch = event.targetTouches[0]
     // 手势滑动时,手势坐标不断变化,取最后一点 的坐标为最终的终点坐标
     endX = touch.pageX
     endY = touch.pageY
     // 这里纪录拖动之后的第一个点,在拖动过程中只纪录一次
     if (judgeX == 0 && judgeY == 0) {
     judgeX = endX
     judgeY = endY
     }
     let Ylength = Math.abs(judgeY - startY)
     let Xlength = Math.abs(judgeX - startX)
     // 根据等边三角形计算角度关系
     lockY = Ylength / Xlength < 1
     if (lockY) {
     // 屏蔽Y轴滑动
     event.preventDefault()
     // 执行X轴滑动动画
     SELECTWRAP_DOM.style.transform = `translateX(${endX - startX}px)`
     }
     // 如果没有判定为X轴滑动,即不会执行动画,只能上下拖动
    })

最后监听touchend事件,对判断数据进行重置以及其他处理
SELECTWRAP_DOM.addEventListener('touchend', (event) => {
     var distanceX = endX - startX
     // 将拖动效果还原,偏移归0
     SELECTWRAP_DOM.style.transform = `translateX(0px)`
     /* 如果当前偏移存在,且偏移量>50,因为小的偏移量可能是用户误操作造成,并且起点和终点的X轴都发生了变化,有可能用户只是点了一下
     那么endX必为0,disctance计算出来就会产生偏移,所以排除此情况,执行自定义指令函数
     */
     // 如果X轴滑动了,执行命令,否则即清空数据,供下次滑动检测
     if (distanceX != 0 && (Math.abs(distanceX) > 50 && lockY) && startX != 0 && endX != 0) binding.value(distanceX)
     // 将缓存的坐标点还原,供下次使用
     startX = 0
     startY = 0
     endX = 0
     endY = 0
     judgeX = 0
     judgeY = 0
     lockY = false
    })

结论:在比值判断之前采取的是固定数值判断,缺点在于不同屏幕下,会存在误判的可能,或者Y轴敏感,或者X轴敏感,体验感都不好。最终采用比值关系之后,效果显著提升。

javascript html 前端
阅读 35 发布于 2 月 25 日
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar
user_QMCj0o9d
1 声望
0 粉丝
关注作者
0 条评论
得票 时间
提交评论
avatar
user_QMCj0o9d
1 声望
0 粉丝
关注作者
宣传栏
目录

自定义手势判断在日历上的应用

在移动端,通常日历展示为当前月的日期纪录,当切换月份的过程中,需要通过手势左滑或者右滑进行月份切换,以下说明如何自行完成一个滑动的手势判断以及逻辑处理

这里借助Vue的自定义指令进行代码阐述,SELECTWRAP_DOM为绑定的DOM元素

bind(el, binding, vnode) {
 var startX = 0
 var startY = 0
 var endX = 0
 var endY = 0
 const SELECTWRAP_DOM = el
 var judgeX = 0
 var judgeY = 0
 var lockY = false
 SELECTWRAP_DOM.addEventListener('touchstart', (event) => {
 // 监听滑动开始,细节见下方
 }
 SELECTWRAP_DOM.addEventListener('touchmove', (event) => {
 // 监听滑动,细节见下方
 }
 SELECTWRAP_DOM.addEventListener('touchend', (event) => {
 // 监听滑动结束,细节见下方
 }
}
首先获取到dom元素之后,对其绑定touchstart事件,也就作为手势判断的起点
SELECTWRAP_DOM.addEventListener('touchstart', (event) => {
     var touch = event.touches[0]
     // 获取当前触控点起点的坐标,包含X,Y
     startX = touch.pageX
     startY = touch.pageY
    })
然后对dom监听touchmove事件,但是此事件只获取起始的第一个点,作为手势判断的终点
SELECTWRAP_DOM.addEventListener('touchmove', (event) => {
     var touch = event.targetTouches[0]
     // 手势滑动时,手势坐标不断变化,取最后一点 的坐标为最终的终点坐标
     endX = touch.pageX
     endY = touch.pageY
     // 这里纪录拖动之后的第一个点,在拖动过程中只纪录一次
     if (judgeX == 0 && judgeY == 0) {
     judgeX = endX
     judgeY = endY
     }
     let Ylength = Math.abs(judgeY - startY)
     let Xlength = Math.abs(judgeX - startX)
     // 根据等边三角形计算角度关系
     lockY = Ylength / Xlength < 1
     if (lockY) {
     // 屏蔽Y轴滑动
     event.preventDefault()
     // 执行X轴滑动动画
     SELECTWRAP_DOM.style.transform = `translateX(${endX - startX}px)`
     }
     // 如果没有判定为X轴滑动,即不会执行动画,只能上下拖动
    })

最后监听touchend事件,对判断数据进行重置以及其他处理
SELECTWRAP_DOM.addEventListener('touchend', (event) => {
     var distanceX = endX - startX
     // 将拖动效果还原,偏移归0
     SELECTWRAP_DOM.style.transform = `translateX(0px)`
     /* 如果当前偏移存在,且偏移量>50,因为小的偏移量可能是用户误操作造成,并且起点和终点的X轴都发生了变化,有可能用户只是点了一下
     那么endX必为0,disctance计算出来就会产生偏移,所以排除此情况,执行自定义指令函数
     */
     // 如果X轴滑动了,执行命令,否则即清空数据,供下次滑动检测
     if (distanceX != 0 && (Math.abs(distanceX) > 50 && lockY) && startX != 0 && endX != 0) binding.value(distanceX)
     // 将缓存的坐标点还原,供下次使用
     startX = 0
     startY = 0
     endX = 0
     endY = 0
     judgeX = 0
     judgeY = 0
     lockY = false
    })

结论:在比值判断之前采取的是固定数值判断,缺点在于不同屏幕下,会存在误判的可能,或者Y轴敏感,或者X轴敏感,体验感都不好。最终采用比值关系之后,效果显著提升。