移动端触摸手势检测工具,根据元素的 touchstart, touchmove, touchend 事件计算相关的滑动、缩放和旋转操作,以及触摸事件结束后的惯性滑动。
滑动、缩放以及旋转都是当前时刻相对元素上一时刻的状态计算的,因此从触摸开始(
touchstart)到触摸结束(touchend)之间总的滑动距离和旋转角度,需要将每一时刻值进行累加,而缩放大小则需要累乘。
npm install js-motion自动监听 options.target 元素的手势操作:
importMotionfrom'js-motion'constMode=Motion.ModeconstDirection=Motion.Directionconstmotion=newMotion({target: '#target',mode: Mode.realtime,direction: Direction.xy})motion.onTouchstart(e=>{// ...})motion.onTouchmove(({ x, y, scale, angle },e)=>{// ...})motion.onTouchend(({ x, y },e)=>{// ...})如果已经进行了目标元素的 touch 事件绑定,则需要传入相关的事件,便可以检测到 event.target 元素的手势操作:
importMotionfrom'js-motion'constMode=Motion.ModeconstDirection=Motion.Directionconstmotion=newMotion({mode: Mode.realtime,direction: Direction.xy})consttarget=document.querySelector('#target')target.addEventListener('touchstart',e=>{e.preventDefault()motion.touchstart(e)// 其他操作//...},Motion.isSupportPassive ? {passive: false,capture: true} : false)target.addEventListener('touchmove',e=>{e.preventDefault()motion.touchmove(e,({ x, y, scale, angle })=>{// ...})// 其他操作// ...},Motion.isSupportPassive ? {passive: false,capture: true} : false)target.addEventListener('touchend',e=>{motion.touchend(e,({ x, y })=>{// ...})// 其他操作// ...},Motion.isSupportPassive ? {passive: false,capture: true} : false)推荐使用第一种方式,motion 实例会自动监听 options.target 元素的相关事件。
touchmove 的执行模式:
Mode.realtime- 实时模式:即每一次
touchmove事件进行处理计算滑动距离。Mode.frame- 帧模式:即一帧内的多个
touchmove事件合并,进行一次处理,计算总的滑动距离。
注意:如果可以尽量使用 realtime 模式,因为部分浏览器对 touchmove 事件触发的频率已经做了优化,使用 frame 会出现跨度较大的问题。
motion 监听的移动方向:
Direction.x- 只监听水平方向的移动:只计算水平方向的移动距离,垂直方向的移动距离始终为 0。
Direction.y- 只监听垂直方向的移动。只计算垂直方向的移动距离,水平方向的移动距离始终为 0。
Direction.xy- 同时监听水平和垂直方向的移动。同时计算水平和垂直两个方向的移动距离。
constmotion=newMotion(options)实例化时指定 options.target 选项,被动监听 motion.touch
options.target- 需要监听触摸事件的目标元素,可选。options.mode- 指定touchmove的执行模式,默认为Mode.realtime。options.direction- 指定监听的移动方向,默认为Direction.xy。
监听 options.target 的 touchstart 操作,并将 touchstart 事件回调。
motion.onTouchstart(e=>{// e 是 options.target 的 touchstart 事件})监听 options.target 的 touchmove 操作,并将滑动距离和 touchmove 事件回调。
motion.onTouchmove(({ x, y, scale, angle },e)=>{// x 是水平方向的移动距离// y 是垂直方向的移动距离// scale 是缩放比率// angle 是旋转的角度// e 是 options.target 元素的原生 touchmove 事件})监听 options.target 的 touchend 操作,并将需要惯性滑动的距离和 touchend 事件进行回调。
回调的滑动距离为 0 时则表示滑动停止:
options.direction=Direction.x- 回调惯性滑动距离分量x为0时,表示惯性滑动停止options.direction=Direction.y- 回调惯性滑动距离分量y为0时,表示惯性滑动停止options.direction=Direction.xy- 回调惯性滑动距离分量x和y都为0时,表示惯性滑动停止
注意:如果没触发惯性滑动,只会触发一次回调;如果触发惯性滑动,则会进行多次回调,直到滑动停止。
motion.onTouchend(({ x, y },e)=>{// x 是水平方向的惯性移动距离// y 是垂直方向的惯性移动距离// e 是 options.target 元素的原生 touchend 事件})实例化时没有指定 options.target 元素,则需要主动调用该方法,并传入 touchstart 事件,告诉 motion 实例滑动操作即将开始。
consttarget=document.querySelector('#target')target.addEventListener('touchstart',e=>{// 主动传入 touchstart 事件,触摸开始motion.touchstart(e)},Motion.isSupportPassive ? {passive: false,capture: true} : false)注意:在调用 motion.touchmove() 之前始终需要先调用一次 motion.touchstart(),保证 motion 可以正确计算开始触摸的位置。
实例化时没有指定 options.target 元素,则需要主动调用该方法,并传入 touchmove 事件,告诉 motion 实例滑动操作正在进行。
consttarget=document.querySelector('#target')target.addEventListener('touchmove',e=>{// 主动传入 touchmove 事件,正在滑动motion.touchmove(e,({ x, y, scale, angle })=>{// x 是水平方向的滑动距离// y 是垂直方向的滑动距离// scale 是缩放比率// angle 是旋转的角度})},Motion.isSupportPassive ? {passive: false,capture: true} : false)实例化时没有指定 options.target 元素,则需要主动调用该方法,并传入 touchend 事件,告诉 motion 实例触摸已经结束。达到惯性滑动条件,则会进行惯性滑动。
consttarget=document.querySelector('#target')target.addEventListener('touchend',e=>{// 主动传入 touchend 事件,触摸结束motion.touchend(e,({ x, y })=>{// x 是水平方向的惯性滑动距离// y 是垂直方向的惯性滑动距离})},Motion.isSupportPassive ? {passive: false,capture: true} : false)