现在,为智能触摸手机创建直观的用户界面时,最重要的部分不再是单纯的视觉效果,而是要创建出能很好地处理用户触摸交互的界面。对于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事件那样来监控鼠标按键的状态。下面是基本的拖拽功能的实现:

  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事件,从而提供了一套设备无关的事件机制。这套机制使用起来和监听普通的事件一样简单,你只需将传统的事件名替换成一些事件函数:

  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事件来缩放,旋转任何元素。

  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函数:

  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事件框架。

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

  1. iOS / Android 移动设备中的 Touch Icons

    上次转载了一篇<将你的网站打造成一个iOS Web App>,但偶然发现这篇文章的内容有些是错误的——准确来说也不是错误,只是不适合自半年前来的情况了(也可以说是iOS7 之后的时间)—— ...

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

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

  3. 获得touch事件,jquery绑定事件监听器,ios设备上打开touch状态以响应focus,active等伪类

    2. 默认的监听方式 document.addEventListener('touchstart', function(){ alert('hello'); }, false); 使用jquery时 ...

  4. RxHttp 完美适配Android 10/11 上传/下载/进度监听

    1.前言 随着Android 11的正式发布,适配Android 10/11 分区存储就更加的迫切了,因为Android 11开始,将强制开启分区存储,我们就无法再以绝对路径的方式去读写非沙盒目录下的 ...

  5. 非root Android设备上Tcpdump的实现

    通常我们在Android应用中执行某个命令时会使用"Runtime.getRuntime().exec("命令路径")"这种方式,但是当我们执行抓包操作时,使用 ...

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

    http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://g ...

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

    2015苹果新品发布会上微信成为首批支持iPhone 6s 和 iPhone 6s Plus 上 3D Touch 功能的 App.通过 3D Touch,微信用户将可以通过更精减的操作完成基本任务, ...

  8. 如何查看Android设备上的分区信息

    Android设备上,一般都会存在一块eMMC存储芯片来存放系统和用户数据,甚至部分的引导程序. 一般设备出厂时,各个厂商都会将这块存储芯片分成很多的分区,每个分区内存放不同的内容.具体分区的布局每个 ...

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

    自:http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http:/ ...

随机推荐

  1. C++ 代码性能优化 -- 循环分割提高并行性

    对于一个可结合和可交换的合并操作来说,比如整数的加法或乘法, 我们可以通过将一组合并操作分割成 2 个或更多的部分,并在最后合并结果来提高性能. 原理: 普通代码只能利用 CPU 的一个寄存器,分割后 ...

  2. 多线程Demo

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. 手机的touch事件(基于jquery)

    javascript代码: $.swipe=function(opt){   var o = $.extend({     mainSelector:"",     swipeLe ...

  4. 2016032901 - ubuntu安装jdk

    在ubuntu上安装jdk,然后网上大部分相同的教程配置,结果运行java,javac,java -version总是出现莫名奇妙的问题. 原先配置完之后,运行java -version后出现下面内容 ...

  5. 2014年度辛星html教程夏季版第七节

    经过前面六节的学习,我们大致清楚了HTML教程中的基础内容,那么接下来我们开始继续向后推进,可以说,下面我们介绍一下HTML中的区块. ***************区块*************** ...

  6. Asynchronous socket communication

    来源:http://www.codeproject.com/Articles/1608/Asynchronous-socket-communication 本地下载 Download source f ...

  7. range([start], stop[, step]):产生一个序列,默认从0开始

    range([start], stop[, step]):产生一个序列,默认从0开始 >>> l = range(10) >>> l [0, 1, 2, 3, 4, ...

  8. Global中的事件执行顺序

    The Global.asax file, sometimes called the ASP.NET application file, provides a way to respond to ap ...

  9. 1319-n皇后问题

    描述 在n×n 格的棋盘上放置彼此不受攻击的n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于在n×n格的棋盘上放置n个皇后,任何2 个皇后不放在同一 ...

  10. SDUT 1646 Complicated Expressions

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1646 题意 : 话说我根本没读题,,,因为实在 ...