本人在做一个简易项目时,需要实现如下效果:菜单宽度超过屏宽,靠手指左右滑动显示完成内容(菜单本身还是二级菜单)
很显然需要用到touchstart/touchmove/touchend事件。
但本人对touch事件无甚了解,也因此频频碰壁,折腾许久才实现这一效果。
现将相关关键点记录如下。
1、获取touch事件的手指位置
本人最初使用【e.pageX】,但只有苹果平台支持。后来得知需要使用【e.touches[0].pageX】
e.touches这一数组存储了当前每根手指的位置。
2、二级菜单多次刷新
应事先效果是:绑定click事件。点击下拉,再点击上滑。
可能触屏过于敏感,导致多次触发click事件。
解决方式为:
[1]、为动画中的div添加【isAnimate】属性(动画结束后设为false),若为true则直接return
[2]、若二级菜单高度大于0,则不进行下拉操作,直接return
3、为滑动添加缓停效果后常常失灵
缓停效果模仿触屏平台浏览器的滑动效果,根据手指移动速度,在手指触摸结束后还有一段缓冲。
通过记录两次touchmove事件的坐标,和时间,dx/dt即可求得横向速度。
缓停的实现如下:
1、速度 X 摩擦系数
2、当前位置 + 速度
3、边界判断
速度<1时停止动画。每次触摸开始清定时器。

var curX = 0; var curT = 0; var speedX = 0; var friction = 0.9; function toEnd(){ if( Math.abs(speedX) < 1 ){ return; } var tbc = true; speedX *= friction; self.thisX += speedX; if(self.thisX > 0) { self.thisX = 0; tbc = false;} else if(self.thisX < dw) { self.thisX = dw; tbc = false; } self.style.marginLeft = self.thisX + 'px'; if(tbc) { self.timer = setTimeout(toEnd, 33); } }
但本人多次实验发现,在一定条件下两次touchmove求得的间隔为0,即缓停效果消失。
故而本人在计算速度时添加了一个判断。之后便能正常运作了。

var x = e.touches[0].pageX; var t = (new Date).getTime(); var dt = Math.max((t - curT) / 20, 1); if( Math.abs(x - curX) > 1) { speedX = Math.floor((x - curX) / dt); curX = x; curT = t; }