当前位置: 首页 > 工具软件 > DHTMLX Touch > 使用案例 >

html5 移动端的点击事件 touch

姚自强
2023-12-01

TOUCH 事件

首先 touch 包含三类事件,它们分别是:touchstart、touchmove、touchend 。望文生义这种本能相信你应该会有,但在这里我还是有必需对这三个词进行一翻不必要的解释。

授课时间
touchstart:手指触摸到一个 DOM 元素时触发。

 
touchmove:手指在一个 DOM 元素上滑动时触发。

 
touchend:手指从一个 DOM 元素上移开时触发。

这三个事件又分别对应三个相同的触摸列表:

授课时间
touches:正在触摸屏幕的所有手指的一个列表。

 
targetTouches:正在触摸当前 DOM 元素上的手指的一个列表。

 
changedTouches:涉及当前事件的手指的一个列表。

Touch 属性
事件对应的三个列表虽然名字不一样,但是它们里面装的东西都是差不多的,包含了当前事件的一些相关信息,比如:一些坐标信息。

TouchList {0: Touch, length: 1}
length:1
0:Touch
    clientX:65 // 触摸点在浏览器窗口中的横坐标
    clientY:18 // 触摸点在浏览器窗口中的纵坐标
    force:1 // 触摸点压力大小
    identifier:0 // 触摸点唯一标识(ID)
    pageX:65 // 触摸点在页面中的横坐标
    pageY:18 // 触摸点在页面中的纵坐标
    radiusX:11.5 // 触摸点椭圆的水平半径
    radiusY:11.5 // 触摸点椭圆的垂直半径
    rotationAngle:0 // 旋转角度
    screenX:560 // 触摸点在屏幕中的横坐标
    screenY:175 // 触摸点在屏幕中的纵坐标
target:div#touchLog 触摸目标
__proto__:Touch
__proto__:TouchList
上面就是一个 TouchList 列表。它对应的就是前面提到的三种事件(touchstart、touchmove、touchend)中的一种,在触发时生成的一个对象列表。列表里最有用的就是 Touch 对象了,Touch 对象里存放着对应事件的一些相关的信息,我们就是通过这种个事件里这些属性的有机结合来实现各种效果。

通过上面的 radiusX,radiusY,rotationAngle 这三个属性就可以计算出你的手指触摸手机屏幕时的一个接触面,只不过这个接触面是用一个近似的椭圆来表示,也就是说它不是一个真正意义上的接触面,而是一个大概的接触面。相信心细的朋友应该会看到 TouchList 对象里有一个 length 属性,并且它的值为 1  ,这说明当前只有一个手指触发了事件(比如:touchstart 事件),换句话说,此时你只有一个手指放到了手机屏幕上,这个手指对应的一些信息存放在 Touch 对象里。因为只有一个手指放在了屏幕上,所以这个 TouchList 里只有一个 Touch 对象,并且是第一个下标为 0 。TouchList 列表里还有一个 target 属性,这个应该很好理解,就是触摸的目标。

为了让你能更加立体地理解上面的这些属性,我专门从网上找了一段话来作为补充:

来自 mozilla
1.Touch.identifier:此 Touch 对象的唯一标识符。 一次触摸动作(我们指的是手指的触摸)在平面上移动的整个过程中,该标识符不变。 可以根据它来判断跟踪的是否是同一次触摸过程,此值为只读属性。

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

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

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

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

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

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

 
8.Touch.radiusX:能够包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径。这个值的单位和 screenX 相同。只读属性。

 
9.Touch.radiusY:能够包围用户和触摸平面的接触面的最小椭圆的垂直轴(Y轴)半径。这个值的单位和 screenY 相同。只读属性。

 
10.Touch.rotationAngle:它是这样一个角度值:由radiusX 和 radiusY描述的正方向的椭圆,需要通过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面。只读属性。

 
11.Touch.force:手指挤压触摸平面的压力大小,从0.0(没有压力)到1.0(最大压力)的浮点数。只读属性。

 
12.Touch.target:当这个触点最开始被跟踪时(在 touchstart 事件中),触点位于的HTML元素。哪怕在触点移动过程中,触点的位置已经离开了这个元素的有效交互区域,或者这个元素已经被从文档中移除。需要注意的是,如果这个元素在触摸过程中被移除,这个事件仍然会指向它,但是不会再冒泡这个事件到 window 或 document 对象。因此,如果有元素在触摸过程中可能被移除,最佳实践是将触摸事件的监听器绑定到这个元素本身,防止元素被移除后,无法再从它的上一级元素上侦测到从该元素冒泡的事件。只读属性。

TOUCH 滑动方向判断

方法一:

当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和纵坐标startY;
当触发touchmove事件时,在获取此时手指的横坐标moveEndX和纵坐标moveEndY;最后,通过这两次获取的坐标差值来判断手指在手机屏幕上的滑动方向。

思路:

用touchmove的最后坐标减去touchstart的起始坐标,X的结果如果正数,则说明手指是从左往右划动;X的结果如果负数,则说明手指是从右往左划动;Y的结果如果正数,则说明手指是从上往下划动;Y的结果如果负数,则说明手指是从下往上划动。

// 原生js addeventListener 事件监听方法
 var mybody = document.getElementsByTagName('body')[0];

    //滑动处理

    var startX, startY, moveEndX, moveEndY, X, Y;   

    mybody.addEventListener('touchstart', function(e) {

        e.preventDefault();

        startX = e.touches[0].pageX;

        startY = e.touches[0].pageY;

    });

    mybody.addEventListener('touchmove', function(e) {

        e.preventDefault();

        moveEndX = e.changedTouches[0].pageX;

        moveEndY = e.changedTouches[0].pageY;

        X = moveEndX - startX;

        Y = moveEndY - startY;

        if ( X > 0 ) {alert(‘向右’);}

        else if ( X < 0 ) {alert(‘向左’);}

        else if ( Y > 0) {alert(‘向下’);}

        else if ( Y < 0 ) { alert(‘向上’);}

        else{alert(‘没滑动’); }

    });
    
// jquery $.on('touchstart') 添加事件方法

    var startX, startY, moveEndX, moveEndY, X, Y;   

    $('body').on('touchstart', function(e) {

        e.preventDefault();

        startX = e.originalEvent.touches[0].pageX; // jquery把浏览器本身创建的事件对象给包装了,想访问原始事件对象 就要通过originalEvent属性来访问

        startY = e.touches[0].pageY;

    });

    $('body').on('touchmove', function(e) {

        e.preventDefault();

        moveEndX = e.originalEvent.touches[0].pageX;

        moveEndY = e.originalEvent.touches[0].pageY;

        X = moveEndX - startX;

        Y = moveEndY - startY;

        if ( X > 0 ) {alert(‘向右’);}

        else if ( X < 0 ) {alert(‘向左’);}

        else if ( Y > 0) {alert(‘向下’);}

        else if ( Y < 0 ) { alert(‘向上’);}

        else{alert(‘没滑动’); }

    });

然而在实际的操作中,手指的上下滑动很难做到直上直下,只要稍微有点斜,只要稍微有点斜,就会被X轴的判断先行接管,而与我们实际的操作意愿相背离。此时就需要添加特殊的判断技巧,修改代码如下(工作中用如下代码即可):

// 原生js addeventListener 事件监听方法 jquery方法同上就不写了
    var mybody = document.getElementsByTagName('body')[0];

   

    //滑动处理

    var startX, startY, moveEndX, moveEndY, X, Y;   

    mybody.addEventListener('touchstart', function(e) {

        e.preventDefault();

        startX = e.touches[0].pageX;

        startY = e.touches[0].pageY;

    }, false);

    mybody.addEventListener('touchmove', function(e) {

        e.preventDefault();

        moveEndX = e.changedTouches[0].pageX;

        moveEndY = e.changedTouches[0].pageY;

        X = moveEndX - startX;

        Y = moveEndY - startY;

        

        if ( Math.abs(X) > Math.abs(Y) && X > 0 ) {

            alert("向右");

        }

        else if ( Math.abs(X) > Math.abs(Y) && X < 0 ) {

            alert("向左");

        }

        else if ( Math.abs(Y) > Math.abs(X) && Y > 0) {

            alert("向下");

        }

        else if ( Math.abs(Y) > Math.abs(X) && Y < 0 ) {

            alert("向上");

        }

        else{

            alert("没滑动");

        }

    });

 

以上代码,在测试时仍不能达到预期的效果,因为还有一个问题——body的元素的高仔细查查,发现其值是0;
故还应该在此基础上添加以下代码:

    var mybody = document.getElementsByTagName('body')[0];

    var h = document.documentElement.clientHeight;

        mybody.style.height = h + 'px';

到此,已实现了手机移动端手指的上滑、下滑、左滑和右滑操作。

方法二

  1. 滑动屏幕事件使用HTML5中的touchstart滑动开始事件和touchmove滑动结束事件。
  2. 方向的判断:以起点做平面坐标系,与终点连线做直线,直线与x正半轴计算角度;我们以45度角为方向分割线,如:只要滑动角度大于等于45度且小于135度,则判断它方向为向上滑。如图所示:
  3. 使用Math.atan2来计算起点与终点形成的直线角度。

注意:标准坐标系与屏幕坐标系并不相同,在屏幕坐标系中,上半轴为负值,要实现转换,只需要调换Y坐标起点与终于位置即可。

// 原生js addeventListener 事件监听方法 jquery方法同上就不写了
  var h = document.documentElement.clientHeight,

          mybody = document.getElementsByTagName('body')[0];

          mybody.style.height = h + 'px';

 

 

        //返回角度

        function GetSlideAngle(dx,dy) {

          return Math.atan2(dy,dx) * 180 / Math.PI;

        }

 

        //根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动

        function GetSlideDirection(startX,startY, endX, endY) {

          var dy = startY - endY;

          var dx = endX - startX;

          var result = 0;

 

          //如果滑动距离太短

          if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {

             return result;

          }

          var angle = GetSlideAngle(dx, dy);

          if (angle >= -45 && angle < 45) {

             result = 4;

          }else if (angle >= 45 && angle < 135) {

             result = 1;

          }else if (angle >= -135 && angle < -45) {

             result = 2;

          }else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {

             result = 3;

          }

          return result;

        }

 

 

        //滑动处理

        var startX, startY;

        mybody.addEventListener('touchstart', function (ev){

          ev.preventDefault();

          startX = ev.touches[0].pageX;

          startY = ev.touches[0].pageY; 

        }, false);

 

        mybody.addEventListener('touchmove', function (ev){

          var endX, endY;

          ev.preventDefault();

          endX = ev.changedTouches[0].pageX;

          endY = ev.changedTouches[0].pageY;

 

        var direction = GetSlideDirection(startX, startY, endX, endY);

        switch (direction){

          case 0:

            alert("没滑动");

            break;

          case 1:

            alert("向上");

            break;

          case 2:

            alert("向下");

            break;

          case 3:

            alert("向左");

            break;

          case 4:

            alert("向右");

            break;

          default:          

        } 

      }, false);
 类似资料: