TAT.dnt 超小 Web 手势库 AlloyFinger 原理
In Web开发 on 2016年11月11日 by view: 6,136
2

目前 AlloyFinger 作为腾讯手机 QQ web 手势解决方案,在各大项目中都发挥着作用。
感兴趣的同学可以去 Github 看看:

https://github.com/AlloyTeam/AlloyFinger

在腾讯,如:兴趣部落、QQ 群、QQ 动漫、腾讯学院、TEDxTencent、 AlloyTeam、腾讯 CDC 等多个部门、团队和项目都在使用 AlloyFinger。如下图所示:

QQ截图20161111085311

基本上只要有图像裁剪、图像查看的地方都会使用到 AlloyFinger。因此 AlloyFinger 也入选了腾讯 code 平台的精品组件:

QQ截图20161111091518

除了国内外的项目团队都在使用 AlloyFinger,国内外的各大 IT 网站也进行了转载报道,作为超级小的手势库,腾讯的 web 项目为什么不选择 hammerjs 而选择 AlloyFinger? 下面从各个角度、架构、原理上进行一下分析。

体积

QQ截图20161111090429

可以看到 hammerjs 体积远远大于 AlloyFinger,对于手机 QQ web 加载速度性能追求极致的同学来说,使用 hammerjs 的大小是不可以接受的!
那么,为什么 hammerjs 这么大?看下架构设计便可知晓。

架构设计

 

QQ截图20161111090621

图片1

其实,hammerjs 抽象出的 Class 还没有列举全,还有许多。所以过度工程化,导致其体积特别大。
一个好的设计并不需要把每个逻辑点都抽象出来,局部过程化,整体 OO 是可以。如 AlloyFinger 的设计。仅仅只有 Vector2 和 AlloyFinger,在 touchstart、touchmove、touchend 是可以 trigger 出相关的手势事件的,简单、直接!hammerjs 能支持的手势,AlloyFinger 都能支持。

具体实现

众所周知,浏览器暴露了四个事件给开发者,touchstart touchmove touchend touchcancel,在这四个事件的回调函数可以拿到 TouchEvent。
TouchEvent:
touches:当前位于屏幕上的所有手指动作的列表
targetTouches:位于当前 DOM 元素上的手指动作的列表
changedTouches:涉及当前事件的手指动作的列表
TouchEvent 里可以拿到各个手指的坐标,那么可编程性就这么产生了。

Tap 点按

图片2

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

longTap 长按

longtap

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

swipe 划

swipe

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

pinch 捏

这个手势是使用频率非常高的,如图像裁剪的时候放大或者缩小图片,就需要 pinch。

QQ截图20161111093632

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

rotate 旋转

QQ截图20161111093842

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

cross_show

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

QQ截图20161111094608

所以,物理引擎里经常用 cross 来计算转动惯量,因为力矩其实要是力乘矩相当于面积:

QQ截图201611110946526

总结

主要的一些事件触发原理已经在上面讲解,还有如 multipointStart、doubleTap、singleTap、multipointEnd 可以看源码,不到 200 行的代码应该很容易消化。trigger 手势事件的同时,touchStart、touchMove、touchEnd 和 touchCancel 同样也可以监听。
详细的 Vector2 和 AlloyFinger 代码可以去 Github 上查阅:
https://github.com/AlloyTeam/AlloyFinger
任何意见或者建议欢迎提 issue:
https://github.com/AlloyTeam/AlloyFinger/issues

 

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2016/11/11568/

  1. ceau 2017 年 5 月 24 日

    是叉乘,不是差乘

  2. blobs 2016 年 11 月 12 日

    已经用上•ᴗ•

发表评论