mishe / blog

前端碰上的问题或体会
230 stars 39 forks source link

touch 事件深究 #77

Open mishe opened 8 years ago

mishe commented 8 years ago

touch系事件概述

touch系事件是触屏设备上的一系列事件,当用户触摸屏幕时及进行一系列操作时发生的事件。 包含touchstart, touchmove, touchend事件。

程序思路

我们将焦点集中在事件这个抽象对象上去,例如当手指在触摸屏上移动过程中发生的touchmove事件,我们去查找此事件相关的属性,根据前后事件的发生(例如touchstart和touchend事件),去判断是否符合程序触发任务的条件(例如当用户向上滑动时你要做一个页面动画)。

事件模式

需要指出的是,touch事件同其他dom事件一样(因为本身就属于dom事件,只不过用在触屏设备的新增html5事件而已),用addEventListener绑定,在事件处理时使用e.prevantDefault()来阻止默认事件执行(例如你在滚动div时,使用它来阻止页面滚动),使用e.stopPropagation()来阻止事件向上冒泡,等等。

对象解释

touchList:touch类对象组成的数组 touch对象:touch对象表示一个触点,触点属性包含identifier, target, clientX/clientY, pageX/pageY, screenX/screenY, force(接触面最小椭圆角度)/radiusX(接触面最小椭圆X轴)/radiusY(接触面最小椭圆Y轴)/rotationAngle(chrome上目前还是带有webkit前缀的webkitForce(压力)/webkitRadiusX/webkitRadiusY/webkitRotationAngle), 其中identifier用来标识该触点,因为屏幕上可能同时存在多个触点。

事件解析

touchstart事件

1、发生条件:当用户触摸到屏幕时,发生touchstart事件。

实验:

一根手指触摸屏幕: 此时触发一个touchstart事件 两根手指触摸屏幕: 先后发生两个touchstart事件 summary:touchstart是按触摸点(严格说应该是分离的两个触摸点)来定义的。(关于触发原理,这里是臆想而已,这个问题已在知乎上提问,届时更新)

2、属性解析

changedTouches属性: 一个touchList数组,表示该事件发生时发生改变的触点,一般都是该触点本身。

此时来说说indetifier这个属性吧:

实验:

一 个 TouchList 对象,包含了所有当前接触触摸平面的触点的 Touch 对象,无论它们的起始于哪个element 上,也无论它们状态是否发生了变化。【摘自https://developer.mozilla.org】

targetTouches属性:

一个 TouchList 对象,是包含了如下触点的 Touch 对象:触摸起始于当前事件的目标 element 上,并且仍然没有离开触摸平面的触点.【摘自https://developer.mozilla.org】

targetTouches和touches联合起来做一个实验:

Fa的touchstart中touches和targetTouches对象都仅仅包含一个touch对象,对应Fa的触摸点。 Fd的touchstart中touches和targetTouches对象是一样的,包含两个touch对象,分别是Fa和Fd对应的触摸点。

touchmove事件

当触摸点在触摸平面上移动时,触发touchmove事件。

实验:

var test=document.getElementById('test'); 
window.addEventListener('touchmove',function(e){ 
    console.log('move on the window'); 
    console.log(e); 
},false);
test.addEventListener('touchmove',function(e){
    e.preventDefault(); //e.stopPropagation();
    console.log('move on the test');
    console.log(e); 
    if(e.changedTouches[0].clientY>420){
    //因为该测试中div#test的高度为400px且起点为(0,0) 
        if(test.parentNode){
            test.parentNode.removeChild(test); 
            console.log('remove') 
        }
    }
},false);

我们依然简单地让Fa从div#test滑出到body区域。

现象:在控制台上可以看出:

当div#test被删除后,只执行了div#test上的touchmove, 但已经不再冒泡到window。 注意:remove打印出来之前,事件已经冒泡到了window,所以随后有一个window的touchend的回调被执行。

touchend事件

当触摸点离开屏幕时触发touchend事件。 实验: