iPhone, Android等设备上的Touch和Gesture

现在,为智能触摸手机创建直观的用户界面时,最重要的部分不再是单纯的视觉效果,而是要创建出能很好地处理用户触摸交互的界面。对于Web应用而言,这意味着使用touch事件来取代传统的mouse事件。在Dojo 1.7中,新的touch API可以帮助您简化这一步骤。

本文是Touching and Gesturing on the iPhone的更新版,该文最早发布于2008年

引言
在我们讨论Dojo 1.7中那些帮助创建可触摸界面的新功能之前,先来了解下底层的技术、概念。Apple在发布iPhone的同时引入了两种新的事件概念:touch和gesture。Touch用来保存有多少手指接触在屏幕上以及这些触点的位置、触点的状态。Gesture则是用来描述用户在交互时到底做了哪些更高层次上的行为,比如:pinching,rotating,swiping,double-tapping等等。

Touch事件在众多平台上都得到支持(最初在iOS上建立起的touch事件模型已被作为标准写入W3C Touch Events specification),而原生的Gesture事件在很多地方都没有得到支持,在iOS上的Gesture事件也仅限于其平台支持的少量gesture。

Touches
当你将一个手指放到屏幕上时,将触发Touch事件的生命周期。每次手指触摸屏幕,一个新的touchstart事件将会产生。每次手指离开,一个touchend事件将会触发。如果你触摸屏幕并移动手指,那touchmove事件将会触发。如果有太多手指触摸屏幕或者有另一个行为(比如说手机操作系统的信息推送) 打断了touch,一个touchcancel 事件会被触发。

Touch事件列表:

  • touchstart: 当手指触摸到屏幕时被触发
  • touchend: 当手指离开屏幕时被触发
  • touchmove: 当手指在屏幕上移动时被触发
  • touchcancel: 当Touch被打断或是有太多手指触摸屏幕时被触发。

虽然看起来Touch事件和Mouse事件之间有一一对应的关系,手指移动就如同使用光标一样,但事实上TouchEvent对象中并不包括那些你可能希望看到的内容。比如,pageX和pageY属性并没有被赋值。这是因为在使用鼠标时,你只有一个交互:光标。但在多点触摸的设备上,你可以在屏幕的左边同时按下两根手指并在屏幕的右边用另一根手指进行点击,这三个接触点都会被系统注册。

为了一次提供所有接触点的信息,每一个TouchEvent对象有一个保存着每个触点信息的属性。同时,它还有另外两个属性:其中一个保存着由当前目标节点触发的触点信息,另一个仅保存着当前事件相关的触点信息。

  • touches: 包含当前屏幕上每个触点信息的列表。
  • targetTouches: 和touches类似,但只包含在触发该Touch事件的节点上的触点信息。
  • changedTouches: 包含每个接触状态变化的触点信息的列表。

为了更好的理解这些列表,让我们来看一些例子。

  • 当你将手指放到屏幕上,三个列表中的信息相同。
  • 当你将第二根手指放到屏幕上,touches 将包含两个触点的信息。如果第二根手指放在第一根手指所在的节点上,targetTouches 将同样包含两个触点的信息,否则它将之包含第二个手指的触点信息。 changedTouches 将只包含第二个手指的触点信息,因为是由第二个手指的接触触发的此次Touch事件。
  • 如果同时用两根手指接触屏幕,那changedTouches将包含着两个手指的触点信息。
  • 如果你移动手指,唯一会发生变化的是changedTouches。它将包含所有移动手指的触点信息。
  • 当你移开一根手指,它对应的触点信息将被从touches和targetTouches中移除,并会被添加到changedTouches列表中。
  • 当你移开最后一根手指,touches和targetTouches列表将被清空,并且changedTouches将只包含最后一根手指的触点信息。

使用这些列表,可以比较清楚的了解用户到底在进行那些操作。想象一下做一个JavaScript版的超级玛丽——你会需要知道玩家在按哪个方向键,而在玩家想要发射火球或者跳跃时,你需要监控玩家到底是按在哪个虚拟的按钮上。

现在我们已经讨论了保存屏幕上手指触点信息的几个列表,但我们还没有谈到这些触点信息到底有哪些。这些触点信息包含一些和MouseEvent对象中类似的信息。下面是这些具体信息内容的列表:

  • clientX: 触点相对于viewport的X坐标(不包括页面滚动的偏移量)
  • clientY: 触点相对于viewport的Y坐标(不包括页面滚动的偏移量)
  • screenX: 相对屏幕的X坐标
  • screenY: 相对屏幕的Y坐标
  • pageX: 触点相对于整个页面的X坐标 (包括页面滚动的偏移量)
  • pageY: 触点相对于整个页面的Y坐标 (包括页面滚动的偏移量)
  • identifier: 数字ID编号,用以区别每个触点。
  • target: 触点所在的DOM节点

为智能手机开发Web应用时很烦人的一点是即使你为你的应用设置好了viewport,在屏幕上移动你的手指可能会移动整个页面。幸运的是,touchmove事件对象有一个preventDefault方法,可以被用来阻止页面被移动。

使用Touch API实现拖拽
在触摸设备上实现拖拽功能非常方便,因为touchmove事件只有一个手指已经触摸在了屏幕上才会被触发。这意味着我们不需要像使用mousemove事件那样来监控鼠标按键的状态。下面是基本的拖拽功能的实现:

[javascript] view plaincopy

  1. node.addEventListener("touchmove", function(event){
  2. // Only deal with one finger
  3. if(event.touches.length == 1){
  4. // Get the information for finger #1
  5. var touch = event.touches[0],
  6. // Find the style object for the node the drag started from
  7. style = touch.target.style;
  8. // Position the element under the touch point
  9. style.position = "absolute";
  10. style.left = touch.pageX + "px";
  11. style.top = touch.pageY + "px";
  12. }
  13. }, false);

Dojo 1.7中更好的Touch
使用底层Touch事件有一个问题,如果你正在创建的应用需要可以运行在触摸设备及使用鼠标的设备上,你将不得不使用两套event listener。Dojo 1.7中新的dojo/touch模块标准化了Touch和Mouse事件,在支持触摸的设备上使用Touch事件机制,在其它设备上自动蜕化成使用Mouse事件,从而提供了一套设备无关的事件机制。这套机制使用起来和监听普通的事件一样简单,你只需将传统的事件名替换成一些事件函数:

[javascript] view plaincopy

  1. require([ "dojo", "dojo/touch" ], function(dojo, touch){
  2. dojo.connect(dojo.byId("myElement"), touch.press, function(event){
  3. // handle a mousedown/touchstart event
  4. });
  5. dojo.connect(dojo.byId("myElement"), touch.release, function(event){
  6. // handle a mouseup/touchend event
  7. });
  8. });

Gestures
在iOS设备上,一个Gesture事件在两个或更多手指触摸屏幕时被触发。如果任何手指落在你正监听Gesture事件(gesturestart, gesturechange,gestureend)的节点上,你将收到对应的Gesture事件。

Gesture事件提供一个GestureEvent对象,该对象包含以下属性:

  • rotation: 使用手指旋转的角度。
  • scale: 用户使用手指进行pinch和push操作时产生的一个倍数。如果大于1,用户则在进行push操作,小于1,则用户在进行pinch操作。

当同时监听了Gesture事件和Touch事件,则事件触发模式如下:

  • touchstart 第一个手指接触屏幕时触发
  • gesturestart 第二个手指接触屏幕时触发
  • touchstart 第二个手指接触屏幕时触发
  • gesturechange 两个手指都在屏幕上时,每次手指在屏幕上移动时触发
  • gestureend 第二个手指 离开屏幕时触发
  • touchend 第二个手指 离开屏幕时触发
  • touchend 第一个手指 离开屏幕时触发

Resizing and rotating with the Gestures API

使用CSStransform, width, 和height属性,我们可以很简单地使用这些Gesutre事件来缩放,旋转任何元素。

[javascript] view plaincopy

  1. var width = 100,
  2. height = 200,
  3. rotation = 0;
  4. node.addEventListener("gesturechange", function(event){
  5. var style = event.target.style;
  6. // scale and rotation are relative values,
  7. // so we wait to change our variables until the gesture ends
  8. style.width = (width * event.scale) + "px";
  9. style.height = (height * event.scale) + "px";
  10. style.webkitTransform = "rotate(" + ((rotation
  11. + event.rotation) % 360) + "deg)";
  12. }, false);
  13. node.addEventListener("gestureend", function(event){
  14. // Update the values for the next time a gesture happens
  15. width *= event.scale;
  16. height *= event.scale;
  17. rotation = (rotation + event.rotation) % 360;
  18. }, false);

Dojo 1.7中更好的Gesture
Dojo 1.7包含了一个新的包dojox/gesture,它提供了处理触摸设备上更复杂的Gesture的能力。其中dojox/gesture/Base模块定义了一套可扩展出自定义Gesture的框架,除此之,该包还提供了一些常用Gesture的支持,如tap,tap and hold,double tap,and swipe。

使用dojox gesture非常简单。就像使用dojo/touch一样,为了监听某一个Gesture,你只需使用dojo.connect绑定一个Gesture,将传统的事件名替换为一个Gesture函数:

[javascript] view plaincopy

  1. require([ "dojo", "dojox/gesture/swipe", "dojox/gesture/tap" ],
  2. function(dojo, swipe, tap){
  3. dojo.connect(dojo.byId("myElement"), swipe, function(event){
  4. // handle swipe event
  5. });
  6. dojo.connect(dojo.byId("myElement"), tap.doubletap, function(event){
  7. // handle double tap event
  8. });
  9. });

将来,dojox/gesture将包含更多的Gesture种类,比如pinching和zooming。现在它提供了几种原本难以处理的事件的支持,以及一套跨平台可扩展的Gesture事件框架。

时间: 2024-10-26 20:30:38

iPhone, Android等设备上的Touch和Gesture的相关文章

在android移动设备上登录gmail的时候报password错误解决方法!!!!

今天刚发现的解决的方法:就是登录web端的gmail,查看收件箱应该有no-reply这一帐户给你发过邮件(假设没有,你在移动设备上登录一下gmail).照着邮件里的说明去做,就是生成一个专门应用的password.然后用此password在android移动设备上登录gmail就能够了.我的是这么解决的.

Android设备上opencv开发图像格式

Windows的图像格式和Android移动设备上的图像格式存在差异,使得处理存在一些问题!简单来讲 Camera得到的数据是:YUV,而在移动端设备上显示的数据又是:RGBA, 但是C++程序中处理的数据又是RGB.因此需要做数据的转换.具体的操作示意图如下:                                                             0. 使用前的准备. Camera的使用需要先在AndroidManifest.xml 文件当中加入camera的权

如何在Android和iOS设备上录制游戏?

内容简介 如何在Android和iOS设备上录制游戏? 如何在Android和iOS设备上录制游戏? Xbox One,PS4,Windows 10等都集成了游戏录制功能,而且可以把录制的视频分享到网上. 现在,Android和iOS设备也可以实现游戏录制了. 怎么做呢?我们分为Android和iOS平台来介绍. Android平台 首先下载安装一个App,叫做<Google Play Games>. 运行此App,在菜单中点击<My Game>(英语<我的游戏>的意思

一款Android设备上的智能路由器软件:手机服务站

现在智能电视和盒子的配置越来越高,体验越来越好,那么我们除了用它看看电视电影,打打游戏外,还能干什么呢?它占据着客厅的重要位置,是不是可以做点其他的事情? 例如: 1.用它代替无线路由器给我们的手持设备或笔记本共享网络可以吗? 2.能不能把它做成服务器,用来保存一些不方便或者不需要上传到网络云盘里的文件呢? 3.再或者我想建立一个私人的网站,记录家里的点点滴滴,这些,都可以吗? 4.就算以上都可以做,那我管理起来会不会不方便? 所以,在此向各位推荐一个Android软件来解决以上几个问题,而且还

Android设备上i-jetty环境的搭建-手机上的web服务器

本文主要跟大家分享如何将一台Android设备打造成一个web服务器使用. 编译i-jetty 1.将源码download下来,http://code.google.com/p/i-jetty/downloads/list 2.解压文件,进入pom.xml所在目录,执行命令:mvncleaninstall,参照(http://code.google.com/p/i-jetty/wiki/BuildInstructions) 执行过程中,出现了异常导致失败,是生成classes.dex时内存溢出的

(转)在ios android设备上使用 Protobuf (使用dll方式)

自:http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://game.ceeger.com/forum/read.php?tid=14359&fid=27 如果只能以.Net 2.0下运行,就可以继续往下看了. ============================================================= protobuf是go

微信成为首批支持iPhone 6s /Plus 上 3D Touch 功能的 App

2015苹果新品发布会上微信成为首批支持iPhone 6s 和 iPhone 6s Plus 上 3D Touch 功能的 App.通过 3D Touch,微信用户将可以通过更精减的操作完成基本任务,包括新建聊天,录制小视频,显示我的二维码或免打扰一小时.用户还可以通过 3D Touch 进行图片缩略图预览:或在聊天页面中启动快速操作菜单,选择标为已读 / 未读,免打扰,置顶或删除. 微信还通过3D Touch推出新功能,让用户可以在发送消息时更改字号或者表情图标的大小.相信微信会给用户带来更多

在ios android设备上使用 Protobuf (使用dll方式)

http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://game.ceeger.com/forum/read.php?tid=14359&fid=27 如果只能以.Net 2.0下运行,就可以继续往下看了. ============================================================= protobuf是goog

在Android和iOS设备上调用C++代码

不少Android和iOS项目中,因为种种原因不得不调用C/C++代码.这篇文章主要讲述如何通过Objective-C++.NDK技术在iOS及Android设备上调用C/C++代码. 主要工作原理 主要工作原理,如上图所示.Google Android提供NDK以便支持C/C++代码,而iOS可以通过Objective-C++(*.mm)来支持C/C++代码的编译运行.如果有朋友钻研过Cocos2d-x的话,应该对上述这些内容非常熟悉.好了,废话不多说,开始提供干货. 需要调用的C++代码 我