移动端 之 触摸事件、Tap事件和swipe事件

触摸事件

  • touch是一个事件组,意思不止一个事件,是移动端滑动事件组,touchstart touchmove touchend touchcancel

  • touchstart 当刚刚触摸屏幕的时候触发

  • touchmove 在屏幕上来回的滑动的时候触发

  • touchend 离开屏幕的时候触发

  • touchcancel 被迫终止触摸的时候触发 (例如:来电 消息弹窗)

<div class="box"></div>
<script>
    var box = document.querySelector('.box');
    /*1 touchstart 当刚刚触摸屏幕的时候触发 */
    box.addEventListener('touchstart', function (e) {
        console.log('touchstart');
        console.log(e);
    });
    /*2 touchmove 在屏幕上来回的滑动的时候触发*/
    box.addEventListener('touchmove', function (e) {
        console.log('touchmove');
    });
    /*3 touchend 离开屏幕的时候触发*/
    box.addEventListener('touchend', function (e) {
        console.log('touchend');
        console.log(e);
    });


    /*获取触摸点坐标*/
    /*1. clientX/Y 记录的是基于视口的坐标*/
    /*2. pageX/Y 记录的是基于页面的坐标*/
    /*3. screenX/Y 记录的是基于屏幕的坐标*/
    /*不管什么坐标都可以  需要的是位置的改变 */
</script>

Tap事件

在移动端使用click事件时,会存在大概200~300ms的延迟,如果不自己封装tap事件,那么就需要引入fastclick.js文件

singleTap事件

tap事件是依据touches组来封装的:

自己封装的tap事件:

var tap = function(dom,callback){
    //判断是否滑动过
    var isMove = false;
    //记录响应的速度
    var time = 0;
    dom.addEventListener('touchstart',function(e){
        time = Date.now();
        console.log(e);
    });
    dom.addEventListener('touchmove',function(e){
        isMove = true;
    });
    dom.addEventListener('touchend',function(e){
        var respondTime = Date.now() - time;
        /*tap*/
        if(!isMove && respondTime < 150){
            /*满足条件*/
            callback && callback();
        }
        //重置
        isMove = false;
    });
}

var box = document.querySelector('.box');

tap(box, function(){
    // your code...
    console.log('tap触发了');
});

大神封装的tap事件

    HTMLElement.prototype.myTap = HTMLElement.prototype.myTap || function (callBack) {
      // myTapStart --- touchstart事件时间戳
      // myTapEnd --- 获取touchend事件时间戳
      // timeTap --- myTapStart - myTapEnd <= timeTap 时,被认为触发 tap 事件
      let myTapStart = 0,
        myTapEnd = 0,
        timeTap = 300;
      // 监听 touchstart 事件
      this.addEventListener('touchstart', function (e) {
        // 获取touchstart事件的时间戳
        myTapStart = e.timeStamp;
        // changedTouchs 是事件对象 TouchEvent 上面的属性,上面存储了一个当前操作的信息。
        let point = e.changedTouches[0];
        this.strX = point.pageX;
        this.strY = point.pageY;
        // 锁死 touchmove 事件
        this.isMove = false;
      }, false);
      // 监听 touchmove 事件
      this.addEventListener('touchmove', function (e) {
        let point = e.changedTouches[0];
        let changeX = point.pageX - this.strX;
        let changeY = point.pageY - this.strY;
        if (Math.abs(changeX) > 10 || Math.abs(changeY) > 10) {
          this.isMove = true;
        }
      }, false);
      // 监听 touchend 事件
      this.addEventListener('touchend', function (e) {
        // 获取 touchend 事件的时间戳
        myTapEnd = e.timeStamp;
        const isTimeTap = myTapEnd - myTapStart;
        if (!this.isMove && isTimeTap <= timeTap) {
          callBack();
        }
      }, false);
    };


    let box = document.querySelector(".box");

    box.myTap(function () {
      // your code...
      console.log("单击事件myTap");
    });

doubleTap事件

HTMLElement.prototype.doubleTap = HTMLElement.prototype.doubleTap || function (callBack) {
    // isTouchEnd
    // lastTime
    // lastTx lastTy --- 合理范围内的误差
    // firstTouchEnd --- 第一次 触发 touchend 事件
    // body --- iphone os
    // dTapTimer --- 定时器
    // startTx startTy --- 获取 touchstart 的位置
    // startTime --- 兼容 iphone os
    let isTouchEnd = false,
        lastTime = 0,
        lastTx = null,
        lastTy = null,
        firstTouchEnd = true,
        body = document.body,
        dTapTimer, startTx, startTy, startTime;
    // 监听 touchstart
    this.addEventListener('touchstart', function (e) {
        // 清除定时器s
        if (dTapTimer) {
            console.log('dTapTimer');
            clearTimeout(dTapTimer);
            dTapTimer = null;
        }
        // 获取 touchstart 的位置
        const touches = e.touches[0];
        startTx = touches.clientX;
        startTy = touches.clientY;
    }, false);

    // 监听 touchend
    this.addEventListener('touchend', function (e) {
        const 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) {
            console.log('单次点击的 touchstart 的位置和 touchend 的位置允许 6px 的误差');
            // 两次 tap 的间隔确保在 500 毫秒以内
            if (duration < 501) {
                // 本次的 tap 位置和上一次的 tap 的位置允许一定范围内的误差
                if (lastTx !== null && Math.abs(lastTx - endTx) < 45 && lastTy !== null && Math.abs(lastTy - endTy) < 45) {
                    firstTouchEnd = true;
                    lastTx = lastTy = null;
                    callBack()
                }
            } 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')) {
        console.log('iphone os');
        body.addEventListener('touchstart', function (e) {
            startTime = Date.now();
        }, true);

        body.addEventListener('touchend', function (e) {
            let noLongTap = Date.now() - startTime < 501;
            if (firstTouchEnd) {
                firstTouchEnd = false;
                if (noLongTap && e.target === this) {
                    dTapTimer = setTimeout(function () {
                        // 永远不会执行setTimeout里面的代码,因为在 click 中清除了 dTapTimer
                        firstTouchEnd = true;
                        lastTx = lastTy = null;
                        console.log('fire double tap event at iphone os');
                        callBack()
                    }, 400);
                }
            } else {
                firstTouchEnd = true;
            }
        }, true);

        // iOS 上手指多次敲击屏幕时的速度过快不会触发 click 事件
        body.addEventListener('click', function (e) {
            if (dTapTimer) {
                clearTimeout(dTapTimer);
                dTapTimer = null;
                firstTouchEnd = true;
            }
        }, false);

    }
}
let box = document.querySelector('.box')
box.doubleTap(function() {
    console.log('doubleTap 触发了')
})

longTap事件

  <script>
    HTMLElement.prototype.longTap = HTMLElement.prototype.longTap || function (callBack) {
      let startTx, startTy, lTapTimer;
      this.addEventListener('touchstart', function (e) {
        // 清除定时器
        if (lTapTimer) {
          clearTimeout(lTapTimer);
          lTapTimer = null;
        }
        // 获取 touchstart 位置
        let touches = e.touches[0];
        startTx = touches.clientX;
        startTy = touches.clientY;

        lTapTimer = setTimeout(function () {
          callBack()
          console.log('fire long tap event');
        }, 1000);

        e.preventDefault();
      }, false);

      this.addEventListener('touchmove', function (e) {
        // 获取 touchmove 位置
        let touches = e.touches[0],
          endTx = touches.clientX,
          endTy = touches.clientY;
        // 定时器存在 并且 发生了 touchmove 清除定时器
        if (lTapTimer && (Math.abs(endTx - startTx) > 5 || Math.abs(endTy - startTy) > 5)) {
          clearTimeout(lTapTimer);
          lTapTimer = null;
        }
      }, false);

      this.addEventListener('touchend', function (e) {
        if (lTapTimer) {
          clearTimeout(lTapTimer);
          lTapTimer = null;
        }
      }, false);

    }

    let box = document.querySelector('.box')
    box.longTap(function() {
      // your code ...
      console.log('longTap 触发了')
    })

swipe事件

  HTMLElement.prototype.swipe = HTMLElement.prototype.swipe || function (callBack) {
      let isTouchMove, startTx, startTy;
      this.addEventListener('touchstart', function (e) {
        let touches = e.touches[0];

        startTx = touches.clientX;
        startTy = touches.clientY;
        isTouchMove = false;
      }, false);

      this.addEventListener('touchmove', function (e) {
        isTouchMove = true;
        e.preventDefault();
      }, false);

      this.addEventListener('touchend', function (e) {
        if (!isTouchMove) {
          return;
        }

        let 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) {
            callBack('left')
            console.log('fire swipe left event');
            isSwipe = true;
          } else if (distanceX < -20) {
            callBack('right')
            console.log('fire swipe right event');
            isSwipe = true;
          }
        } else {
          if (distanceY > 20) {
            callBack('up')
            console.log('fire swipe up event');
            isSwipe = true;
          } else if (distanceY < -20) {
            callBack('down')
            console.log('fire swipe down event');
            isSwipe = true;
          }
        }

        if (isSwipe) {
          console.log('fire swipe event');
        }
      }, false);
    }

    let box = document.querySelector('.box')
    box.swipe(function (direct) {
      // your code ...
      console.log('swipe 触发了' + direct)
    })

猜你喜欢

转载自www.cnblogs.com/houfee/p/10413687.html
今日推荐