我爱编程让前端飞前端

Mobile H5 手势解决方案

2018-11-12  本文已影响19人  EdmundChen

背景

在手机H5页面开发需求中,我们经常遇到一些手势需求,例如:pinch(捏), rotate(旋转)multipointStart(多点触摸)pressMoveTapdoubleTaplongTapswipe。以上手势没有原生事件的支持,所以需要自己通过一些方法实现。
这篇文章旨在介绍原生触摸事件,以及如果利用原生事件实现各种手势。
demo
github touch-finger
扫描二维码体验

image.png

Mobile 触摸事件列表 TouchEvent

Touch Interface

Interface Interface 描述了触摸事件的单个触摸点Touch对象是不可变的; 创建一个后,其属性不得更改。

Attributes

TouchList Interface

TouchList Interface 定义触摸事件的各个联系点列表。 TouchList对象是不可变的; 创建一个后,其内容不得更改。

Attributes

TouchEvent Interface

定义touchstarttouchendtouchmovetouchcancel事件类型。 TouchEvent对象是不可变的; 在创建并初始化一个之后,其属性不得更改。

Attributes

说明:
* touchstart事件: 这必须是刚刚对当前事件激活的触摸点列表。
* touchmove事件: 这必须是自上次事件以来已移动的触摸点列表。
* touchendtouchcancel: 这必须是刚从表面移除的触摸点列表。

手势实现原理

具体实现

浏览器暴露了四个事件给开发者,touchstart touchmove touchend touchcancel,在这四个事件的回调函数可以拿到TouchEvent

TouchEvent:

Tap点按

image.png

移动端click有300毫秒延时,tap的本质其实就是touchend。但是要判断touchstart的手的坐标和touchend时候手的坐标x、y方向偏移要小于30。小于30才会去触发tap。

longTap 长按

image.png

touchstart开启一个750毫秒的settimeout,如果750ms内有touchmove或者touchend都会清除掉该定时器。超过750ms没有touchmove或者touchend就会触发longTap

doubleTap 双击

touchstart 记录一次当前的事件戳,然后把下一次出发touchstart的时间戳减法上一次的,如果小于250毫秒,并且偏移量小于30则清除Tap的settmeout,调用doubleTap事件

swipe划

image.png

这里需要注意,当touchstart的手的坐标和touchend时候手的坐标x、y方向偏移要大于30,判断swipe,小于30会判断tap。那么用户到底是从上到下,还是从下到上,或者从左到右、从右到左滑动呢?可以根据上面三个判断得出,具体的代码如下:

  _swipeDirection(x1, x2, y1, y2) {
    return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
  }

pinch捏

image.png

如上图所示,两点之间的距离比值求pinch的scale。这个scale会挂载在event上,让用户反馈给dom的transform或者其他元素的scale属性。

rotate旋转

image

如上图所示,利用内积,可以求出两次手势状态之间的夹角θ。但是这里怎么求旋转方向呢?那么就要使用差乘(Vector Cross)。 利用cross结果的正负来判断旋转的方向。

image

cross本质其实是面积,可以看下面的推导:

image

其他手势

略。

其他解决方案: http://hammerjs.github.io/

参照: https://github.com/AlloyTeam/AlloyFinger

上一篇 下一篇

猜你喜欢

热点阅读