移动端的touch事件(二)

前面一篇简单说明了一下touch对象的一些基本信息,这里就对touch对象中,所支持的事件类型进行一些说明。

对前一章节的补充

在写前一篇文章时,主要参考的内容来自于MDNtouch对象的介绍,当时有说到TouchEvent.type的值的问题,内如参考:TouchEvent,但是又在W3C中看到了相关的内容,在W3C中,TouchEvent.type的取值中,只包含:touchstart,touchend,touchmove,touchcancel事件,详情请查看:List of TouchEvent types,并没有touchentertouchleave的事件类型,然后又查看了MDN中相关的文章,才发现,这两个事件类型,已经被移除,详情请查看:touchentertouchleave,这里呢,就对这个问题,进行一下说明。

下面就开始就还在支持的四种touch事件类型,进行一下说明,本来这里是想说一下touch事件中,我们可以用来操作的一些属性值的,但是写到后来,却写成了关于这些事件的触发情况,也就是说,在什么时候,会触发什么样的事件。OK,继续吧。

touch类型的概述

在上一篇中,我也说过一个问题,并且进行了一个简单的验证,就是touchmove类型,是和touchstart事件同时触发的,并且在touchend之前,不会再被触发第二次,所以,我认为这个touchmove事件,是一个很鸡肋的类型,感觉没有什么用的样子,也许是各浏览器厂商都还没有来得及实现这个功能吧,所以就先保留着了。

而另外一个touchcancel类型,这个就没有怎么用到过了,但是有一点我是不明白的,就是,touchend是和touchstart匹配出现的,那么是不是也就意味着,touchcancel每次出现时,都是出现在touchend之后呢?如果是出现在touchend之后,那么,touchcancel存在的意义是什么呢?

那么就来测试一下,touchcancel在什么时候出现了:本部分参考自:W3C Touch EventsMDN TouchEvent

主要分为四点:

  • 由于同步事件,或者UA(用户代理)取消了touch事件。(W3C)
  • 由于某个事件取消了触摸,例如触摸过程被一个模态的弹出框打断。(MDN)
  • 触点离开了文档,而进入了浏览器的界面元素,插件或其他非文档区域。(W3C,MDN)
  • 当产生的触点超过了设备支持的个数时,从而导致TouchList中最早的Touch对象被取消。(W3C,MDN)

关于上面说到的四点,后面的两点暂且不说,但是前面的两点,中的一些语句,跟我再前一篇中小结部分所说的touch事件对事件的影响是完全相悖的。

比如12中都提到的取消事件,当touch事件被触发之后,也就代表着,JS当前执行的事件就是这个touch事件,其他所有的事件都会被阻塞,所有不可能是被其他事件取消的的touch事件,那么只有touch事件本身,把自己取消了。这个接下来进行验证。

但是2中说的模态框会取消touch事件,这个我是无论如何都不能理解的,模态框肯定得是在一个事件的回调中被触发的,那么如果模态框是在touch事件之后被触发,那么由于touch阻塞了JS,那么这个模态框的事件,就只有等到touch事件执行完毕才会被触发,这样就不可能会取消事件,而如果这个回调是在touch事件之前就触发,那么也只有在模态框的回调执行完之后,才执行touch事件吧?或者说,touch事件有更高的优先级?这个我觉得不可能吧(没有看懂相关的根据)。所以,这两种情况导致的touchcancel出现的情况,我是想不明白的。

下面的测试,只是基于我本人的手机端得出的结果,只能说明一个片面的问题,不代表一个真正的原因,请根据真实情况,重新认识该方面的知识。

首先是,在touchstart事件内部,使用代码,阻止默认动作,阻止冒泡,按理说,这个时候,touch事件是被取消掉的,所以,这个时候,会触发touchcancel事件的,并且,为了能了解事件触发的顺序,我写了如下一个简单的测试代码:


var html = "";
document.addEventListener("touchstart",touchstart,false);
document.addEventListener("touchMove",touchMove,false);
document.addEventListener("touchEnd",touchEnd,false);
document.addEventListener("touchcancel",touchcancel,false);

function touchstart(e){
    e = e || window.event;
    html += "touchStart";
    $("touchStart").innerHTML = html;
    e.stopPropagation();
    e.preventDefault();
}

function touchMove(){
    html += "touchMove";
    $("touchMove").innerHTML = html;
}

function touchEnd(){
    html += "touchEnd";
    $("touchEnd").innerHTML = html;
}

function touchcancel(){
    html += "touchCancel";
    $("touchCancel").innerHTML = html;
}

function $(id){
    return document.getElementById(id);
}


这样,上面的代码,就可以让我能看到一个问题,就是如果我再touchstart触发时,即阻止了默认动作,也阻止了冒泡,那么对于之后的touchmovetouchendtouchcancel这三个类型会有什么样的影响呢?

如果你有兴趣,可以在移动端打开下面的网址,看下您手机上,对这个事件是不是有影响呢?移动端网址:www.zhangyunling.com/study/2014/20140921/touch-4.html;

插入图片:

注意哦,这里因为不要滑动太久,太久的话,因为touchmove一直被触发,则会链接非常多的touchmove字符。

该图片是我本人手机的测试结果:这个时候,是分别触发了touchstarttouchmovetouchend,但是并没有触发touchcancel

但是有一点,这里想要说明一下,也许你已经注意到了,如果在上述页面中,手指滑动的比较长的距离的话,touchmove是被多次触发的,这和我前一篇中,写的关于touchmove只会被触发一次的描述是相反的。

为什么呢?这里的代码,和之前的代码,其实差距也就是在touchstart时,这里阻止了默认动作,而之前没有,所以,现在进行下面的修改:


function touchstart(e){
    html += "touchStart";
    $("touchStart").innerHTML = html;
}


对于没有阻止默认动作和冒泡的方法,移动端查看地址:www.zhangyunling.com/study/2014/20140921/touch-5.html;

插入图片:

由图片中,可以看出,这个时候,只触发了touchstarttouchmove事件,但是却没有触发touchend事件,也就是说,touchend事件并不是一定会被触发的,就算执行了touchstart事件,也不一定会有touchend事件出现。

并且,这个时候,touchmove事件,也确实如我们在上一篇中看到的情况,如果touchstart事件并没有阻止默认动作,那么touchmove事件,只会被执行一次,这也和我们之前一篇文章中,所提到的touch事件阻止了计时器的执行部分所说的相吻合了(这个在IOS下,也是会有这个情况的)。

注:这个touchend事件不被触发的情况,应该是和系统有关,因为之前在IOS系统下,手指在屏幕滑动是可以触发touchend事件的,可是,这里我在自己的Android机上,却看不到这个现象。

touchcancel事件的触发

在前面的测试中,都没有触发touchcancel的情况,就算是我们在touchstart时,阻止了默认动作,依然没有触发touchcancel类型的touch事件,那么具体什么时候,才能触发这个呢?

这里所说的只能算是一个片面的问题,暂时只发现两个情况,可以触发touchcancel事件:

  • 手机浏览器中,有左右滑动翻页的功能,如果试图左右滑动翻页,但是但是没有翻页成功(或者是自己在翻页时,不想再翻而停止这个操作),可以触发touchcancel事件。
  • 在touchcancel事件之前的一个事件,使用阻止默认动作的操作,关于这个,接下来的代码中,可以验证这个。

首先是,如果只绑定了touchstart事件和touchcancel事件,那么阻止touchstart事件的默认动作,页面结构不变,JS做如下改动:


var html = "beigin";
document.addEventListener("touchstart",touchstart,false);
document.addEventListener("touchcancel",touchcancel,false);

function touchstart(e){
    e = e || window.event;
    html += "-touchStart";
    $("touchStart").innerHTML = html;
    e.stopPropagation();
    e.preventDefault();
}

function touchcancel(){
    html += "-touchCancel";
    $("touchCancel").innerHTML = html;
}

function $(id){
    return document.getElementById(id);
}


此时,就可以触发touchcancel事件,效果如下图所示:

移动端查看地址:www.zhangyunling.com/study/2014/20140921/touch/touch-6.html;

但是,如果在阻止touchstart的默认动作的情况下,同时监听了touchmovetouchend事件,则不会不会再触发touchcancel事件,所以,这个取消默认动作而触发的touchcancel事件的情况,只有取消touchcancel事件紧挨着的前一个touch事件的默认动作才会触发。

下面当监听touchmove事件时,取消touchmove事件的默认动作(代码修改省略),得到的效果图如下:

从图中的touchstart的内容中可以看出,如果只是阻止了touchmove的默认事件,并不会触发touchcancel事件的,移动端页面请查看:www.zhangyunling.com/study/2014/20140921/touch-7.html;

那如果对touchend进行阻止呢?

请查看图示:

由图中可以看出,这个时候,依然没有触发touchcancel事件,移动端页面查看地址:www.zhangyunling.com/study/2014/20140921/touch-8.html;

是不是只有绑定两个事件,其中一个取消默认动作,才可以触发touchcancel事件呢?这进行一下测试:www.zhangyunling.com/study/2014/20140921/touch-9.html;

图示:

由图中可以看出,依然没有触发touchcancel事件,所以说,阻止其他事件的默认动作,并不能百分比的触发touchcancel事件,只有阻止touchstart事件,并且没有touchmovetouchend事件时,才能触发touchcancel事件。

上述结论,只是基于我本人的手机进行的简单的测试,不能证明其广泛的适用性,只是想要依据此来对各事件的触发情况,进行一个简单的了解。如有问题,请提出,谢谢!

小结

touch事件的触发,在AndroidIOS系统下,是有区别的,比如本文中出现的在touchendAndroid下,有时并不会被触发的情况,在IOS下,应该是都可以触发的,所以,当希望使用touch事件时,请多多注意。

本文只是一个测试,也算是是一个我对touch事件的一点点简单的认识,如有描述错误或者理解错误的地方,恳请指教,非常感谢!

PS:发现自己还是不能一段一段的写东西,因为总是记不住之前原本的思想,和想要写的内容。本篇内容,写到最后,就感觉有些乱了,而且感觉也没有写出什么实质的内容。

本文地址:http://www.zhangyunling.com/?p=230

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

移动端的touch事件(二)》有2个想法

  1. 匿名说道:

    这样理解touchcancel是不是更简易一点,例如你在浏览器里玩HTML5的游戏,这个时候你女朋友打电话进来了,就会触发touchcancel事件,游戏的作者就可以在这里做暂停游戏、自动存档等操作

    1. 你这个比喻很好啊,我还真是没有想到过这种情况,我刚才使用touch-6的代码试了一下,还真是能在显示来电界面之前,触发一次touchcancel事件,你的这个想法太棒了。感谢提出这个新的理解,学习了,谢谢啦。