博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript移动设备Web开发中对touch事件的封装实例
阅读量:4635 次
发布时间:2019-06-09

本文共 5290 字,大约阅读时间需要 17 分钟。

在触屏设备上,一些比较基础的手势都需要通过对 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不会触发clickif( ~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,需要的朋友看看吧~

原文转自:

转载于:https://www.cnblogs.com/yuqingfamily/p/5907251.html

你可能感兴趣的文章
ASP.NET MVC Identity 兩個多個連接字符串問題解決一例
查看>>
#include<bits/stdc++.h>包含C++的所有头文件
查看>>
Vue插槽 slot
查看>>
HDOJ1004
查看>>
Eclipse中部分快捷键
查看>>
LintCode: Unique Characters
查看>>
从一个OutOfMemoryError 学会了分析Java内存泄漏问题
查看>>
过滤器与拦截器区别
查看>>
USACO 1.5.4 Checker Challenge
查看>>
第二阶段站立会议7
查看>>
[18]Debian Linux Install GNU GCC Compiler and Development Environment
查看>>
12种排序算法
查看>>
HDU - 5934
查看>>
JAVA多线程
查看>>
ACE(Adaptive Communication Environment)介绍
查看>>
delphi 更改DBGrid 颜色技巧
查看>>
python编码问题
查看>>
POJ 2031 Building a Space Station
查看>>
面向对象1
查看>>
编程开发之--java多线程学习总结(5)
查看>>