zoukankan      html  css  js  c++  java
  • html5移动端长按事件填坑历程

    背景:

    在h5页面,实现长按弹出上拉菜单,我们知道h5没有所谓的长按事件,有些UI组件库封装了长按事件,比如zepto的longtap

    在pc端有鼠标事件(mousedown,mousemove,mouseup),在h5有touch触摸事件(touchstart,touchmove,touchend)

    不能因为需要一个长按事件就引入一个库,这里我们就基于touch触摸事件来实现。

    touch事件群

    • touchstart事件:当手指触摸屏幕的时候触发, 一个手指触摸触发一次;
    • touchmove事件:当手指在屏幕上滑动的时候触发,滑动一下可能触发多次,是一个持续的过程
    • touchend事件: 当手指从屏幕上移开的时候触发;
    • touchcancel事件:当触摸点被中断时触发。例如在触摸过程中突然页面alert()一个提示框

         手指快速点击一个元素,会经过:touchstart  -> touchend --> click

         手指长按一个元素,会经过:touchstart  -> touchend

         手指滑动,会经过:touchstart  ->  touchmove(n次) -> touchend

         综上:

         1、click事件发生在touchstart和touchend之后,这也就是我们所说的移动端点击事件一般有300ms的延迟(可用tap事件替代)

         2、长按的过程是touchstart之后touchend之前,区分长按还是点击,可以根据时间判断,比如大于500ms是长按,小于500ms是点击

         3、如果在点击屏幕的时候手指滑动的话,是不会触发click事件的

     由以上结论,我们就可实现长按事件

     主要逻辑:

          1、在touchstart里定义延迟器,500ms后执行长按逻辑

          2、在touchend里取消延迟器,即在touchstart触发的500ms之内,如果手指从屏幕上移开,则不是长按

          3、在touchmove里取消延迟器,即如果手指在屏幕上滑动,则不是长按

    代码如下:

    <div  @touchstart="onTouchStart(d,$event)"
          @touchmove="onTouchMove($event)"
          @touchend="onTouchEnd">按钮</div>
    
    
    export default {
       data () {
          toucheX: 0,
          toucheY: 0,
          timeOutEvent: ''
       },
       methods: { 
         // 长按弹出上拉操作面板
        onTouchStart (data, e) {
          this.toucheX = e.targetTouches[0].screenX
          this.toucheY = e.targetTouches[0].screenY
          // 开启定时器前先清除定时器,防止重复触发
          this.timeOutEvent && clearTimeout(this.timeOutEvent)
    // 显示上拉面板
    this.timeOutEvent = setTimeout(() => {this.showActionSheet = true }, 500) e.preventDefault() // 阻止系统默认事件 }, onTouchMove (e) { const moveX = e.targetTouches[0].screenX const moveY = e.targetTouches[0].screenY // 解决vivo机型,手指没有move,touchmove事件仍然会调用而导致setTimeout被clear if (this.toucheX !== moveX || this.toucheY !== moveY) { // 手指滑动,清除定时器,中断长按逻辑 this.timeOutEvent && clearTimeout(this.timeOutEvent) } }, onTouchEnd () {
    // 清除定时器,结束长按逻辑
    this.timeOutEvent && clearTimeout(this.timeOutEvent)
    // 若手指离开屏幕,时间小于我们设置的长按时间,则为点击事件 }, } }

    注意:

    1、H5页面长按会触发系统的默认事件,ios和安卓表现不同,如下图。可以使用event.preventDefault()方法阻止后面默认事件的发生

          

    在touchstart中preventDefault,会导致click事件不触发和a链接点击没反应。可以使用tap代替click,但是a标签的话就不太方便了

    在touchmove中preventDefault,会阻止浏览器默认滚动

    2、在某些手机,比如vivo,没有move,但是touchmove事件仍然会触发

    在这种情况,可以根据touch的位置判断手指是否移动,来区分是点击长按或者是滑动

    在touchstart事件中记录touch时的x,y的坐标,然后在touchmove中,再判断touch的位置是否和touchstart中的一样的。

    注意,查看TouchEvent最好在谷歌模拟手机浏览器中查看,不要在真实手机浏览器查看,本人在真实手机浏览器console和alert都看不到详细的信息,疑惑了半天,发现真实手机浏览器虽然看不到信息,但是可以直接取值(TouchList是类数组对象)

    触屏事件的操作信息都存储在TouchEvent类型对象中,此对象属性较多,下面着重介绍下touches、targetTouches与changedTouches

       touches[只读]:手指触摸到屏幕上,所有触摸点的集合;

       targetTouchs[只读]:手指触摸到DOM元素(绑定事件的dom节点)上的触摸点的集合 

       changeTouches[只读]:表示自上次触摸事件以来发生改变的(和触摸事件对应的Touch 对象)

                对于 touchstart 事件, changedTouches是此次事件中新增加的触点。

                对于 touchmove 事件,changedTouches是和上一次事件相比较,发生了变化的触点。

          对于touchend事件,changedTouches 是刚触摸面离开的触点(最后一次离开屏幕的手指的Touch 对象)

          下图中有两个div,只对DIV2绑定了touchstart事件

       当手指第一次触摸到DIV2时,三个对象表示的都是一样的

       再放下第二根手指和第三根手指同时触摸DIV1DIV2时,

            此时touches对象表示的是第一根手指、第二根手指、第三根手指的信息

       此时targetTouches对象表示的是第一根手指和第三根手指的信息,因为绑定touch事件的节点为DIV2

       而changedTouches对象表示的是第二根手指和第三根手指的信息,因为第一根手指没有变化

     综上:

    touchmove时,如果手指从目标元素(绑定事件的dom节点)滑出,targetTouches还会有此触摸点信息

    当一个触摸点从目标元素离开,它的信息将从 touches、targetTouches里移除,但是changedTouches会保留此触摸点信息;

    当最后一个触摸点离开,touches、targetTouches变成空值,而changedTouches保留着最后一个离开的触摸点信息

     扩展:

    Touch.screenX:触点相对于屏幕左边沿的X坐标。只读属性。

    Touch.screenY:触点相对于屏幕上边沿的Y坐标。只读属性。

    Touch.clientX:触点相对于可见视区(visual viewport)左边沿的X坐标。不包括任何滚动偏移。只读属性。

    Touch.clientY:触点相对于可见视区(visual viewport)上边沿的Y坐标。不包括任何滚动偏移。只读属性。

    Touch.pageX:触点相对于HTML文档左边沿的X坐标。当存在水平滚动的偏移时,这个值包含了水平滚动的偏移。只读属性。

    Touch.pageY:触点相对于HTML文档上边沿的Y坐标。当存在水平滚动的偏移时,这个值包含了垂直滚动的偏移。只读属性。

  • 相关阅读:
    437. Path Sum III
    51. N-Queens
    dfs 感悟
    Topological Sorting
    138 Copy List with Random Pointer
    130. Surrounded Regions
    The sum problem
    A + B Again
    Rectangles
    An easy problem
  • 原文地址:https://www.cnblogs.com/caofeng11/p/14213616.html
Copyright © 2011-2022 走看看