从 [长按] 开始学习 web 手势
在项目开发过程中遇到有虚拟键盘开发的需求(如下图),其中删除键需要实现 长按
删除输入框全部内容,由此展开今天要讨论的 web 手势
开发内容。
先放出实现代码:
var $input = document.getElementById('input');
var $delBtn = document.getElementById('delBtn');
var delBtnClock = null;
$delBtn.ontouchstart = function () {
$input.innerHTML = $input.innerHTML.slice(0, -1)
delBtnClock = setTimeout(function () {
$input.innerHTML = '';
}, 500);
}
$delBtn.ontouchend = function () {
clearTimeout(delBtnClock);
delBtnClock = null;
}
关键代码就两句话:
- 在 touchstart 事件中开启计时,这里是计时 500 ms 后,删除输入框内容
- 在 touchend 事件中清除 setTimeout 计时器
如果只是点击,此时 touchend 距离 touchstart 肯定不到 500 ms,计时器在时间没到前已被删除,实现的效果就只是退格;如果长按超过 500 ms,计时器执行,实现输入框内容全部删除。
所以 长按
手势实际上是由 touchstart & touchend & setTimeout 三者共同模拟的效果。
实际上,常规的 js 事件只支持 click、touchstart、touchend、touchmove、touchcancel 这五种与点击相关的事件,如果想实现更多的诸如旋转、放大缩小之类的手势的话,就需要结合上面的五种事件和其他方法来模拟实现了。
下面我将来介绍下传说中的《超级小的 web 手势库:AlloyFinger》
学习 AlloyFinger
业内知名的强大的 web 手势库 hammer.js,总共有 3240 行代码,压缩版的 44.7 kb。与之相比,AlloyFinger 真的称得上超级小了,326 行代码,10 倍的差距,在 “kb 必争” 移动 web 应用里,AlloyFinger 一下就引起了广大开发者的注意,代码量小,功能又齐全,你还要什么单车呢。(我是不是得找人家要下广告费)
在 AlloyFinger 里,手势一共有 14 种,除了常规的 4 种 touchstart,touchmove,touchend 和 touchcancel,还有 10 种由以上 4 种衍生出来的手势如下:
- multipointStart:多点开始
- multipointEnd:多点结束
- tap:点击,效果如 click
- doubleTap:双击
- longTap:长按
- singleTap:单击情况下 250 ms 内没有再次点击(会同时触发 tap,tap 在前)
- rotate:旋转(同时触发 pressMove)
- pinch:放大缩小
- pressMove:单点移动
- twoFingerPressMove:多点移动
- swipe:扫滑,在 touchend 里触发,与 touchmove 稍有不同
原理
- multipointStart
touchstart 中,触点多于 1 个时触发
- multipointEnd
touchend 中,触点少于 2 个时触发(一开始还在想是不是 bug,实际的意思是:最后一个手指离开时触发)
- tap
touchend 中,触点没有移动(移动横纵距离小于 30 px),且没有触发 longTap 时(距离 touchStart 时间少于 750 ms)触发
- doubleTap
touchend 中,有上一次的点击记录 & 点击时间差小于 250 ms & 两次点击间没有移动(移动横纵距离小于 30 px)
- longTap
touchstart 中,添加 750 ms 计时器,在这个时间段内没有松手(touchEnd)移动(touchMove),则触发
- singleTap
touchend 中,单击情况下 250 ms 内没有再次点击
- rotate
touchmove 中,触点多于 1 个,并存在上一次的多点移动记录时触发
- pinch
touchmove 中,触点多于 1 个 & 存在上一次的移动记录 & 有缩放长度记录时触发
- pressMove
touchmove 中,触点等于 1 个
- twoFingerPressMove
touchmove 中,触点多于 1 个
- swipe
touchend 中,触点有移动(移动横纵距离大于 30 px)
生命周期
重点
- 代码中多处使用
setTimeout(function () {}, 0);
, 一方面实现同步转异步,释放线程,另一方面也能确保屏幕滚动时阻止事件的触发 -
滑动时,以最大的移动方向决定水平和竖直方向
_swipeDirection: function (x1, x2, y1, y2) { return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') }
在阅读源码过程中,对关键代码做了注释,点我
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。