这只是个开头
说在最前面, 本文是一个系列文章的开头, 这个系列里我会讲如何用 typescript 开发一款支持 pc 和手机端的手势库 any-touch, 以及通过 jest 让你的代码测试覆盖率 100%.
今天我们先不写代码
今天的文章里我们先不讲代码, 我们讲一下都有哪些手势以及手势的逻辑, 理解了逻辑再写代码就简单了.(即便后面的文章不看, 因为理解了不同手势的区别, 在移动端开发中也可以规避很多 touch 事件产生 bug, 请务必看完本文)
感谢一定要写在最前面
感谢开源的 hammer.js, 是他让我学会了很多手势方面的知识.
还要感谢写这篇文章的作者, 文章地址, 文章详细介绍了关于旋转和缩放手势变化的计算.
那么常用手势有哪些?
回到正题, 常见的手势有: 点击(tap) press(按住) 拖拽(pan) 划过(swipe) 捏合缩放(pinch) 旋转(rotate), 所有的手势在移动端其实都是通过 touch 事件的不同触发时机而区分出的(移动端是 mouseup/mousemove/mousedown).
这里有个 demo, 我把所有的手势识别放在了里面.
tap(点击)
众所周知, 移动端的 click 有 300ms 延迟(浏览器延迟 300ms 为了识别双击操作, 因为移动端浏览器默认双击可以缩放页面), 为了避免 ” 点击穿透 ” 我们创建了 tap 事件, 同时通过 preventDefault 来禁止 click 触发. tap 在 touchend 阶段触发, 说下识别 tap 的必要条件:
触发一次 touchstart 和 touchend.
touchstart 和 touchend 的坐标之间的距离不能超过 2px.
touchstart 触发后,250ms 内必须触发 touchend, 不然会被识别成 press.
doubletap(双击)
2 次连续的 tap(单击)触发双击, 双击的原理如下: 每次 tap 后并不触发 tap, 而是等待 300ms 看是否有双击触发, 如果没有那么 2 次 tap 依次触发, 否则触发双击, 单击不触发. (关于多击更细的原理, 后面我会单独通过源码解析), 必要条件:
2 次点击之间不能超过 300ms.
2 次点击的距离不能超过 9px.
press(按)
按住屏幕不放, 一段时间后触发 press 时间, 触发 press 后, 离开触点, 触发 pressup 事件, 识别的必要条件如下:
touchstart 和 touchmove 之间的距离不能超过 9px.
即便触点不离开屏幕, 251ms 后也会触发 press. 这个 251ms 对应 tap 的必要条件第 3 条.
pan(拖拽)
(1 指或多指)按住屏幕不离开, 每一次移动都会触发 pan. 举几个例子:
轮播效果的拖拽切换, 这个拖拽动作就是 pan.
抽屉 (draw) 组件的拖拽显示更多内容.
选项卡 (tabs) 组件的拖拽显示更多选项卡.
pan 是组件开发中最常用的手势.
swipe(划)
(1 指或多指)按住屏幕快速滑动, 当手指离开屏幕的一瞬间, 触发 swipe. 必要条件如下:
滑动超过一定距离(如 10px).
滑动速度足够快(大于 0.3px/ms).
轮播组件的用 swipe 来表示 ” 切换下一幕 ”.
pinch(啮合)
2 指及以上按住屏幕, 让 2 个手指之间的距离发生变化, 通过距离的变化来表示 pinch 是放大开始缩小. 常见于 gallery 组件, 用来放大 / 缩小图片.
rotate(旋转)
2 指及以上按住屏幕, 通过 2 指形成的直线和坐标系的 x 轴的夹角的变化而出发 rotate. 常用语图片处理, 用来旋转图片.
源码
上面关于手势识别的具体逻辑可以看我的仓库, 地址: https://github.com/383514580/…
未完待续
本次先讲这么多, 后面的文章具体要讲什么看大家的回复想听什么, 期待大家的回复, 本人热爱前端, 但能力有限, 有讲的不对的请大家多多指点.
相关概念解释
点击穿透
当 A / B 两个层上下 z 轴重叠,上层的 A 点击后消失或移开,并且 B 元素本身有默认 click 事件(如 a 标签)或绑定了 click 事件。在这种情况下,点击 A / B 重叠的部分,就会出现点透的现象.