在触屏设备上,一些比较基础的手势都需要通过对 touch 事件进行二次封装才能实现。
zepto 是移动端上使用率比较高的一个类库,但是其 touch 模块模拟出来的一些事件存在一些兼容性问题,如 tap 事件在某些安卓设备上存在事件穿透的 bug,其他类型的事件也或多或少的存在一些兼容性问题。

于是乎,干脆自己动手对这些常用的手势事件进行了封装,由于没有太多真实的设备来进行测试,可能存在一些兼容性问题,下面的代码也只是在 iOS 7、Andorid 4 上的一些比较常见的浏览器中测试通过。

tap事件

tap 事件相当于 pc 浏览器中的 click 效果,虽然在触屏设备上 click 事件仍然可用,但是在很多设备上,click 会存在一些延迟,如果想要快速响应的 “click” 事件,需要借助 touch 事件来实现。

var startTx, startTy;
element.addEventListener('touchstart', function(e) {
var touches = e.touches[0];
startTx = touches.clientX;
startTy = touches.clientY;
}, false);
element.addEventListener('touchend', function(e) {
var touches = e.changedTouches[0],
endTx = touches.clientX,
endTy = touches.clientY;
// 在部分设备上 touch 事件比较灵敏,导致按下和松开手指时的事件坐标会出现一点点变化
if(Math.abs(startTx - endTx) < 6 && Math.abs(startTy - endTy) < 6) {
console.log('fire tap event');
}
}, false);

doubleTap事件

doubleTap 事件是当手指在相同位置范围内和极短的时间内两次敲击屏幕时触发的事件。在部分浏览器下,doubleTap 事件会选中文本,如果不希望选中文本,可以给元素添加 user-select:none 的 css 属性。

var isTouchEnd = false,
lastTime = 0,
lastTx = null,
lastTy = null,
firstTouchEnd = true,
body = document.body,
dTapTimer, startTx, startTy, startTime;
element.addEventListener( 'touchstart', function( e ){
if( dTapTimer ){
clearTimeout( dTapTimer );
dTapTimer = null;
}
var touches = e.touches[0];
startTx = touches.clientX;
startTy = touches.clientY;
}, false );
element.addEventListener( 'touchend', function( e ){
var touches = e.changedTouches[0],
endTx = touches.clientX,
endTy = touches.clientY,
now = Date.now(),
duration = now - lastTime;
// 首先要确保能触发单次的 tap 事件
if( Math.abs(startTx - endTx) < 6 && Math.abs(startTx - endTx) < 6 ){
// 两次 tap 的间隔确保在 500 毫秒以内
if( duration < 301 ){
// 本次的 tap 位置和上一次的 tap 的位置允许一定范围内的误差
if( lastTx !== null &&
Math.abs(lastTx - endTx) < 45 &&
Math.abs(lastTy - endTy) < 45 ){
firstTouchEnd = true;
lastTx = lastTy = null;
console.log( 'fire double tap event' );
}
}
else{
lastTx = endTx;
lastTy = endTy;
}
}
else{
firstTouchEnd = true;
lastTx = lastTy = null;
}
lastTime = now;
}, false );
// 在 iOS 的 safari 上手指敲击屏幕的速度过快,
// 有一定的几率会导致第二次不会响应 touchstart 和 touchend 事件
// 同时手指长时间的touch不会触发click
if( ~navigator.userAgent.toLowerCase().indexOf('iphone os') ){
body.addEventListener( 'touchstart', function( e ){
startTime = Date.now();
}, true );
body.addEventListener( 'touchend', function( e ){
var noLongTap = Date.now() - startTime < 501;
if( firstTouchEnd ){
firstTouchEnd = false;
if( noLongTap && e.target === element ){
dTapTimer = setTimeout(function(){
firstTouchEnd = true;
lastTx = lastTy = null;
console.log( 'fire double tap event' );
}, 400 );
}
}
else{
firstTouchEnd = true;
}
}, true );
// iOS 上手指多次敲击屏幕时的速度过快不会触发 click 事件
element.addEventListener( 'click', function( e ){
if( dTapTimer ){
clearTimeout( dTapTimer );
dTapTimer = null;
firstTouchEnd = true;
}
}, false );
}

longTap事件

longTap 事件是当手指长时间按住屏幕保持不动时触发的事件。

var startTx, startTy, lTapTimer;
element.addEventListener( 'touchstart', function( e ){
if( lTapTimer ){
clearTimeout( lTapTimer );
lTapTimer = null;
}
var touches = e.touches[0];
startTx = touches.clientX;
startTy = touches.clientY;
lTapTimer = setTimeout(function(){
console.log( 'fire long tap event' );
}, 1000 );
e.preventDefault();
}, false );
element.addEventListener( 'touchmove', function( e ){
var touches = e.touches[0],
endTx = touches.clientX,
endTy = touches.clientY;
if( lTapTimer && (Math.abs(endTx - startTx) > 5 || Math.abs(endTy - startTy) > 5) ){
clearTimeout( lTapTimer );
lTapTimer = null;
}
}, false );
element.addEventListener( 'touchend', function( e ){
if( lTapTimer ){
clearTimeout( lTapTimer );
lTapTimer = null;
}
}, false );

swipe事件

swipe 事件是当手指在屏幕上滑动后触发的事件,根据手指滑动的方向又分为 swipeLeft (向左)、swipeRight (向右)、swipeUp (向上)、swipeDown (向下)。

var isTouchMove, startTx, startTy;
element.addEventListener( 'touchstart', function( e ){
var touches = e.touches[0];
startTx = touches.clientX;
startTy = touches.clientY;
isTouchMove = false;
}, false );
element.addEventListener( 'touchmove', function( e ){
isTouchMove = true;
e.preventDefault();
}, false );
element.addEventListener( 'touchend', function( e ){
if( !isTouchMove ){
return;
}
var touches = e.changedTouches[0],
endTx = touches.clientX,
endTy = touches.clientY,
distanceX = startTx - endTx
distanceY = startTy - endTy,
isSwipe = false;
if( Math.abs(distanceX) >= Math.abs(distanceY) ){
if( distanceX > 20 ){
console.log( 'fire swipe left event' );
isSwipe = true;
}
else if( distanceX < -20 ){
console.log( 'fire swipe right event' );
isSwipe = true;
}
}
else{
if( distanceY > 20 ){
console.log( 'fire swipe up event' );
isSwipe = true;
}
else if( distanceY < -20 ){
console.log( 'fire swipe down event' );
isSwipe = true;
}
}
if( isSwipe ){
console.log( 'fire swipe event' );
}
}, false );

上面模拟的事件都封装在 MonoEvent 中了。完整代码地址:https://github.com/chenmnkken/monoevent,需要的朋友看看吧~

原文转自:http://www.jb51.net/article/50663.htm

javascript移动设备Web开发中对touch事件的封装实例的更多相关文章

  1. 第123天:移动web开发中的常见问题

    一.函数库 underscoreJS _.template: <ol class="carousel-indicators"> <!--渲染的HTML字符串--& ...

  2. Web开发中管理ipad屏幕的方向变化

    Web开发中,我们会遇到在手机垂直或水平视角时展示不同状态的情况.下面我来总结一下检测移动设备方向变化的一些方法. 1 使用javascript 直接看代码: <script type=&quo ...

  3. 移动Web 开发中的一些前端知识收集汇总

    在开发DeveMobile 与EaseMobile 主题 的时候积累了一些移动Web 开发的前端知识,本着记录总结的目的,特写这篇文章备忘一下. 要说移动Web 开发与传统的PC 端开发,感觉也没什么 ...

  4. 彻底理解和解决移动WEB开发中CLICK点透问题

    在移动WEB开发中,有时候可能会出现点透问题,本文将围绕这个TAP点透问题,详细的讲述到底什么是点透,为什么会出现点透,如何避免出现点透,如果不可避免的出现了,如何解决解决移动WEB开发中CLICK点 ...

  5. 今日推荐:10款在 Web 开发中很有用的占位图片服务

    设计网站时,将要使用的图像在一开始通常还不存在,这个时候布局是最重要的.然而,图像的尺寸通常是预先设置,实用一些占位图像可以帮助我们更好地预览和分析布局. 如今,有免费的占位图片自动生成工具可以使用, ...

  6. Web 开发中应用 HTML5 技术的10个实例教程

    HTML5 作为下一代网站开发技术,无论你是一个 Web 开发人员或者想探索新的平台的游戏开发者,都值得去研究.借助尖端功能,技术和 API,HTML5 允许你创建响应性.创新性.互动性以及令人惊叹的 ...

  7. Redis在WEB开发中的应用与实践

    Redis在WEB开发中的应用与实践 一.Redis概述: Redis是一个功能强大.性能高效的开源数据结构服务器,Redis最典型的应用是NoSQL.但事实上Redis除了作为NoSQL数据库使用之 ...

  8. web开发中目录路径问题的解决

    web开发当中,目录路径的书写是再常用不过了,一般情况下不会出什么问题,但是有些时候出现了问题却一直感到奇怪,所以这里记录一下,彻底解决web开发中路径的问题,开发分为前端和服务端,那么就从这两个方面 ...

  9. Web开发中设置快捷键来增强用户体验

    从事对日外包一年多以来,发现日本的无论是WinForm项目还是Web项目都注重快捷键的使用,日本人操作的时候都喜欢用键盘而不是用鼠标去点,用他们的话来说"键盘永远比鼠标来的快",所 ...

随机推荐

  1. SSIS Parameter用法

    今天学习SSISParameter的用法,记录学习的过程. Parameters能够在Project Deployment Model下使用,不能在Package Deployment Model使用 ...

  2. Building OpenCASCADE on Debian

    Building OpenCASCADE on Debian eryar@163.com Abstract. When you are familiar with OpenCASCADE on Win ...

  3. 理解javascript中的对话框

    前面的话 通常我们调试程序时,如果需要阻塞效果,则要用到alert().但除了alert()以外,window对象还提供了其他3种对话框.本文将详细介绍window对象中的对话框 定义 系统对话框与在 ...

  4. Android 如何制作九宫格图片(.9.png)

    对于编程人员来说,尤其是前端设计设计师,九宫格图片是必须的(.9.png),对于初学者来说不知道这个九宫格图片有什么用,其实这个九宫格图片实际常用在Android的button组件.要上下拉升的背景图 ...

  5. ksoap调用webservice

    Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发分布 ...

  6. T-SQL:毕业生出门需知系列(三)

    第3课 排序检索数据 3.1 排序数据(ORDER BY) 下面的 SQL 语句返回某个数据库表的单个列.观察其输出,并没有特定的顺序. SELECT prod_name FROM Products; ...

  7. JSP页面静态化

    Ps:好久没写博客了,不是我太懒,是因为苦逼的我出差去上海了,天天加班 刚回成都.... 今天说说jsp页面静态化,知道静态化的朋友都不陌生,说白了就是访问后缀是html 而不是jsp. 没听说过静态 ...

  8. linux中断与异常

    看了<深入理解linux内核>的中断与异常,简单总结了下,如果有错误,望指正! 一 什么是中断和异常 异常又叫同步中断,是当指令执行时由cpu控制单元产生的,之所以称之为异常,是因为只有在 ...

  9. DDD 主题交流会总结及计划

    思维碰撞才能更加进步 2015年5月16日(上周六),我们举行了一次 DDD 主题的交流会,参会者主要是 ENode 群友.以及部分园友,为什么要搞这次交流会?原因很简单,就是希望可以提供对 DDD ...

  10. [ROS] Studying Guidance

    Reference: https://www.zhihu.com/question/35788789 安装指南:http://wiki.ros.org/indigo/Installation/Ubun ...