html5 gesturestart,【HTML5】Touch全解(集合转贴)

参考地址:

插件推荐:(Github搜索即可)

touchy.js(在安卓4.0上面报错,4.1+正常)

iscroll(左|右滑屏效果,触控)

swipe(左右幻灯,触控)

本文从一个多触式网页开发初学者的角度,首先简单介绍一下iOS上的浏览器(这里主要指Safari)所支持的多触式事件模型,然后将触控(Touch)这种简单的动作升级为手势(Gestrue),最后将javascript + html + css构建的应用脱离浏览器,放到iOS设备的屏幕上成为一个本地link并和植物大战僵尸放到一起。

iOS上的Safari也支持click 和mouseover等传统的交互事件,只是不推荐在iOS的浏览器应用上使用click和mouseover,因为这两个事件是为了支持鼠标点击而设计出来的。Click事件在iOS上会有半秒左右的延迟,原因是iOS要highlight接收到click的element。而mouseover/out等事件则会被手指的点击触发。所以,在iOS上,应当抛弃传统的交互事件模型而接受一个新的事件模型。Touch事件和更高级的Gesture事件,能让你的网页交互起来像native应用一样。

处理Touch事件能让你跟踪用户的每一根手指的位置。你可以绑定以下四种Touch事件:

touchstart: // 手指放到屏幕上的时候触发

touchmove: // 手指在屏幕上移动的时候触发

touchend: // 手指从屏幕上拿起的时候触发

touchcancel: // 系统取消touch事件的时候触发。至于系统什么时候会取消,不详。。

上面这几个事件都会冒泡,也都可以取消,每个触摸事件的event对象都提供了在鼠标事件中常见的属性:bubbles,cancelable,view,clientX,clientY,screenX,screenY,detail,altKey,ctrlKey,shiftKey,metaKey除了常见的DOM属性外,触摸时间还包含下列3个用于跟踪触摸属性:

touches // 表示当前跟踪的触摸操作的Touch对象的数组

targetTouches // 特定与事件目标的Touch对象的数组

changeTouches // 表示自上次触摸以来发生了什么改变的Touch对象的数组

每个触摸对象包含下列属性:

clientX // 触摸目标浏览器窗口viewport的X坐标

clientY // ~Y坐标

identifier // 标识触摸唯一ID

pageX // 触摸目标在页面中的X坐标

pageY //~Y坐标

screenX //触摸目标在屏幕中的X坐标

screenY // ~Y坐标

target //触摸的DOM节点目标

Gesture事件则是对touch事件的更高级的封装,主要处理手指slide、rotate、scale等动作,将在下一篇文章详述。

在开始描述touch事件之前,需要先描述一下多触式系统中特有的touch对象(android和iOS乃至nokia最新的meego系统都模拟了类似的对象,这里只针对iOS,因为我只有iPad可用于测试。。)。这个对象封装一次屏幕触摸,一般来自于手指。它在touch事件触发的时候产生,可以通过touch event handler的event对象取到(一般是通过event.changedTouches属性)。

CSS代码

.spirit {             /* 方块的class名称*/

position:absolute;

width:50px;

height:50px;

background-color:red;

}

然后,在body下定义一个接收事件的容器,这里body的height必须是100%才能占满整个viewport:

Html

定义touchstart的事件处理函数,并绑定事件:

Javascript代码

// define global variable

var canvas = document.getElementById(“canvas”),

spirit, startX, startY;

// touch start listener

function touchStart(event) {

event.preventDefault();

if (spirit ||! event.touches.length)return;

var touch = event.touches[0];

startX = touch.pageX;

startY = touch.pageY;

spirit = document.createElement(“div”);

spirit.className = “spirit”;

spirit.style.left = startX;

spirit.style.top = startY;

canvas.appendChild(spirit);

}

// add touch start listener

canvas.addEventListener(“touchstart”, touchStart,false);

首先,我们将方块spirit作为一个全局对象,因为我们现在要测试单根手指所以屏幕上最好只有一个物体在移动(等会有多触实例)。在touchStart这个事件处理函数中,我们也首先判断了是否已经产生了spirit,也就是是否已经有一个手指放到屏幕上,如果是,直接返回。

和传统的event listener一样,多触式系统也会产生一个event对象,只不过这个对象要多出一些属性,比如这里的event.touches,这个数组对象获得屏幕上所有的touch。注意这里的event.preventDefault(),在传统的事件处理函数中,这个方法阻止事件的默认动作,触摸事件的默认动作是滚屏,我们不想屏幕动来动去的,所以先调用一下这个函数。我们取第一个touch,将其pageX/Y作为spirit创建时的初始位置。接下来,我们创建一个div,并且设置className,left,top三个属性。最后,我们把spirit对象appendChild到容器中。这样,当第一根手指放下的时候,一个红色的,50px见方的方块就放到屏幕上了。

然后,我们要开始处理手指在屏幕上移动的事件:

function touchMove(event) {

event.preventDefault();

if (!spirit || !event.touches.length)return;

var touch = event.touches[0],

x = touch.pageX – startX,

y = touch.pageY – startY;

spirit.style.webkitTransform ='translate(' + x +'px, ' + y +'px)';

}

Canvas.addEventListener(“touchmove”, touchMove,false);

在touch move listener中,我们使用webkit特有的css属性:webkitTransform来移动方块,这个属性具体怎么用请google之。建议构造面向iOS设备的网页的时候尽量使用webkit自己的特性,不但炫,更可以直接利用硬件来提高性能。

最后,我们处理touchend事件。手指提起的时候方块从屏幕上移除。

function touchEnd(event) {

If (!spirit)return;

canvas.removeChild(spirit);

spirit =null;

}

canvas.addEventListener(“touchend”, touchEnd,false);

在你的ipad或者iphone上测试一下以上代码。如果不出意外的话,一个完整的多触式web程序就诞生了。。 这种事件处理模式虽然能够满足我们开发多触式网页应用的需求,但是start – move – end的流程有点繁琐,能不能封装一些常用的动作让我们用一个event handler就能解决问题呢。没错,Gesture事件就是为了这个目的设计出来的,它封装了手指的scale, slide, rotate等常用的动作。不过,下一章我们再来讨论这个问题。。 附件是一个更加复杂一些的例子,每根手指放下的时候都会产生一个不同颜色的方块,手指动的时候方块跟着动,手指提起的时候方块消失,请下载查看试用。

通过附件所包含的实例,我们可以看出一些较为隐蔽的特性。首先,这里我们没有再使用event.touches取所有touch的对象,而是使用event.changedTouches这个数组,用来取得所有跟本次事件相关的touch。但是,这里我发现一个奇怪的特性,不知道是我的ipad有问题还是本来就是这样,就是在有多根手指放在屏幕上的时候,如果提起一根手指,touchend事件的changedTouches中会包含所有手指的touch对象,然后,其他几根留在屏幕上的手指会重新触发touchstart,并刷新所有的touch对象(identifier都不一样了)。如果这是一个所有设备都有的特性,那么将给编程者带来一些不便,不知道水果为啥要这么处理。

这篇文章将描述多触式网页开发中对手势(Gesture)事件的处理。

水果设备中的Gesture,广义的说包括手指点击(click),轻拂(flick),双击(double-click),两只手指的分开、闭合(scale)、转动(rotate)等一切手指能在屏幕上做的事情。iOS上设计了了一系列手势来模拟和扩展鼠标操作,比如手指放下后迅速提起会触发click事件,手指向上滑动,停止,会触发body的onscroll事件等等。但是,狭义的Gesture事件,也就是能够addEventListener的GestureEvent对象,却并不是一个非常强大的存在,它只在有两根或多根手指放在屏幕上的时候触发,并且只包含手指分开比例(scale)和手指转动角度(rotation)信息。对于其他各种常用的手势,我们必须利用别的事件来处理。

下面从单根手指的事件开始说起。。。

我们先来考虑一个最简单的手势,手指放下后迅速提起,这个手势做出来后会发生什么?大家当然会想到click,其实在click发生以前,还有很多事情发生,请看下图:

81c053fd016cf79fab0ba66534349a23.png

这里先解释一下什么是clickable element,就是一个绑定了click, mousedown, mouseup, mousemove事件的任何html element(注意,没有绑定事件处理的element不算clickable element)。从这张图可以看出,手指提起的一刹那,首先触发的并不是click事件,而是mouseover和mousemove。然后,系统会判断接收到事件的element的内容是否被改变,如果内容被改变,接下来的事件都不会触发,如果没有改变,会按照mousedown,mouseup,click的顺序触发事件。什么?你问mouseout在哪?这个事件的处理,比较尴尬,上面说的一系列事件都完了以后,如果你再点击一个clickable element,就会触发上一个clickable element的mouseout事件了。。。比较纠结,建议不要在多触版网页上使用mouse out。

那么,如果手指放下后不提起又会发生什么呢?什么都不会发生,没有任何事件会被触发。但是,如果对象是一个img并且有alt属性的话,这个动作将会显示img的alt字符串。如果是一个link的话,这个动作会显示“在新窗口打开连接”选项,但是,不会有任何用户定义事件触发。

最后一种关于单根手指的事件,是放下后滑动手指。注意,在滑动的过程当中,不会触发除touchmove以外的任何事件(请不要试图在这时处理mousemove)。手指在滑动的时候,整个page应该会跟着移动,除非你preventDefault了body的touchmove。当手指停下来后,page的onscroll将会触发。除此之外,没有什么我们熟悉的事情会发生。

这篇文章着重介绍多触式设备上特有的 gesture event(android和iOS对这个事件的封装大同小异)。这个事件是对touch event的更高层的封装,和touch一样,它同样包括gesturestart,gesturechange,gestureend三个事件回调:

gesturestart   // 当有两根或多根手指放到屏幕上的时候触发

gesturechange   // 当有两根或多根手指在屏幕上,并且有手指移动的时候触发

gestureend   // 当倒数第二根手指提起的时候触发,结束gesture

事件处理函数中会得到一个GestureEvent类型的参数,它包含了手指的scale(两根移动过程中分开的比例

)信息和rotation(两根手指间连线转动的角度)信息。

当两根或以上的手指在屏幕上活动的时候,我们可以做出一些较为复杂的手势。这将涉及到普通的mouse事件,touch事件和gesture事件,情况比较复杂。touch已经在第一篇文章里详细介绍,这里就简单带过。

我们还是先看看当分别将两根手指放到屏幕上的时候,会触发哪些事件吧:

第一根手指放下,触发touchstart,除此之外什么都不会发生(请参照第二篇文章,手指提起才会触发mouse的各事件)

第二根手指放下,触发gesturestart

触发第二根手指的touchstart

立即触发gesturechange

手指移动,持续触发gesturechange,就像鼠标在屏幕上移动的时候不停触发mousemove一样

第二根手指提起,触发gestureend,以后将不会再触发gesturechange

触发第二根手指的touchend

触发touchstart!注意,多根手指在屏幕上,提起一根,会刷新一次全局touch!重新触发第一根手指的touchstart,这点和苹果官方网站上介绍的不同。

提起第一根手指,触发touchend

Gesture事件的处理和Touch类似,我们一般会在gesturechange的时候利用GestureEvent对象中的信息来

做一些事情:

var angle = event.rotation;

var scale = event.scale;

这样能够取得scale和rotation信息,然后我们可以:

e.target.style.webkitTransform ='scale(' + e.scale + startScale +') rotate(' + e.rotation +

startRotation +'deg)';

这段代码能让element随着你的两根手指的运动而转动、伸展。以下是一段测试代码,请用

ipad/iphone/android打开: http://wanglingshu.com/wp-content/uploads/ios-gesture.html

还有一件要说明的事情是,对于复杂手势,是否会触发某些鼠标事件?确实有,不过我只找到了一个。不管你的两根手指在屏幕上伸缩还是转动,都不会有任何鼠标事件触发,但当你的两根手指同时朝上或者朝下移动的时候,则会触发某些事件。请看下图:

07f23682a3006a1a297982cfbfc550a4.png

两根手指同时向上或向下滚动,如果target element是一个scrollable element(也就是绑定了mousewheel的element)的话,将会触发mousewheel事件。如果不是scrollable element,则当手指停止移动的时候,会触发onscoll。这里请和第二篇文章的body scroll区别一下,如果你要滚动body,只需要一根手指轻轻拂动屏幕,但是你要滚动一个内部div或者iframe,则需要动用两根手指。

这也是多触式设备一个不太方便的地方。而对于我们开发者来说,这种不方便被放大了。因为从用户体验角度来说,要求用户使用两根手指滚动一个内部element显然是不合适的,而要实现像滚动body一样用一根手指优雅地滚动,我们必须利用touchevent,在它的回调函数中用代码来实现scroll。

四、参考案例

http://www.paulirish.com/demo/multi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值