论坛首页 Web前端技术论坛

指尖下的js -- 多触式web前端开发之一:对于Touch的处理

浏览 15622 次
精华帖 (2) :: 良好帖 (3) :: 新手帖 (13) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-09-14   最后修改:2010-09-15
    水果公司的那些small and cute的设备给我们提供了前所未有的用户体验。当用户在iphone和ipad上运指如飞的时候,那些使用objective-c写出优秀应用的开发人员们心里一定充满了成就感,因为正是他们(而不是水果)让iOS的世界变的丰富多彩。然而对于我们这些以web为自己事业核心的程序员来说,这种让人欲罢不能的多触式体验似乎跟我们关系不大,因为浏览器那一小块地方就是我们和用户的全部交集了。而许多网站为了让iOS的用户能够在多触式体验下使用自己的服务,都专门花钱开发objective-c的本地程序作为自己web service的客户端。

    其实,对于一个web程序员或者一个网站来说,如果你的需求仅仅是让iPhone/iPad用户能够正常使用你的服务,那现有的html4页面完全能够满足(也许需要一点点重构,但是很容易);如果再往上一点,你需要让你的web客户端看起来像是用objective-c实现的一样,也并非不可能,只需要将我们熟悉的javascript搬到iOS设备上来就行。

    本文从一个多触式网页开发初学者的角度,首先简单介绍一下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事件的时候触发。至于系统什么时候会取消,不详。。

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

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

client / clientY:触摸点相对于浏览器窗口viewport的位置

pageX / pageY:触摸点相对于页面的位置

screenX /screenY:触摸点相对于屏幕的位置

identifier: touch对象的unique ID

    我们从一个单根手指触摸的实例开始进入多触式网页的世界。当一根手指放下的时候,屏幕上出现一个方块,手指移动方块也随着移动,手指提起方块消失。首先,让我们定义一下方块的css:

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

         position: absolute;

         width: 50px;

         height: 50px;

         background-color: red;

}


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

<body style=”height: 100%;margin:0;padding:0”>

<div id=”canvas”  style=”position: relative;width:100%;height: 100%;”></div>

</body>


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

// 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都不一样了)。如果这是一个所有设备都有的特性,那么将给编程者带来一些不便,不知道水果为啥要这么处理。

对touch event的介绍我们点到为止,这里给大家推荐两篇文档:

Safari dom additions reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariJSRef/Intro/Intro.html#//apple_ref/doc/uid/TP40001482-CH2g-BAJDAJAG

Safari web content guide:

http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safariwebcontent/Introduction/Introduction.html

对于有志于开发多触式网页应用的程序员来说,apple的developer站点是一个应该经常光顾的地方。
   发表时间:2010-09-16  
lz写的很有技术含量啊, MOBILE WEB很有前景啊,不过现在有很多这方面的framework出来了,不知道LZ是不是在造轮子。

1. 摩托罗拉收购开源Web框架Cappuccino, http://www.iteye.com/news/17459
2. SproutCore, http://www.iteye.com/news/17731-yehuda-kats-leave-engine-yard
3. jQuery Mobile: Touch-Optimized Web Framework for Smartphones & Tablets http://jquerymobile.com/

比起objective-c,这些js的东西我最大的疑问就是:js每次都要下载,这个用户感受很差啊。全部依靠浏览器的cache感觉不是很靠谱。
0 请登录后投票
   发表时间:2010-09-16  

框架是一定要用的,但是一些和传统web不同的技术基础也该普及一下嘛,我也是刚开始入门多触式的web开发,大家共同学习!
对于一些web服务来说,将已有的网页重构为多触式的网页,比开发objective-c客户端还是要便宜多了,objective-c我也在学,学习成本还是比较高的(我比较笨)。。。而且,这样做的最大好处是省去了发布、推广客户端的麻烦,水果app store的审查比较烦。
而且,将html + javascript + css发布为native程序也是可以的。
0 请登录后投票
   发表时间:2010-09-16   最后修改:2010-09-16
代价比用Objective-c重写高?不一定。如果你对HTML和JAVASCRIPT非常熟悉,可能是这样,如果跟我一样是个半吊子,要写出有吸引力的UI还是费功夫的。

尽量使用REST可能对UI的跨平台性有帮助,客户端也就演变成RIA了。
0 请登录后投票
   发表时间:2010-09-17  
ipad的touch通过。
俺测试过android1.6,首先,不支持多touch,android2.2才支持多touch;其次,touch事件貌似也有问题,正在研究中~~~~,希望和楼主多多交流,呵呵~~~~
测试和适配多个设备很麻烦啊,不知道楼主如何解决的,加你好友吧~~~~
0 请登录后投票
   发表时间:2010-09-18  
跨设备测试的确是个艰巨任务,而且水果设备的模拟器还只能在mac下运行,比较郁闷
我现在在ipad上调试都是在viewport上放一个absolute定位的div,然后用createElement来写出调试信息,比较郁闷

android我还真没好好测试过,只读过一些相关文章,事件模型倒是差不多,但是肯定有差异,以后多请教你,:)
lixinlixin2008 写道
ipad的touch通过。
俺测试过android1.6,首先,不支持多touch,android2.2才支持多touch;其次,touch事件貌似也有问题,正在研究中~~~~,希望和楼主多多交流,呵呵~~~~
测试和适配多个设备很麻烦啊,不知道楼主如何解决的,加你好友吧~~~~

0 请登录后投票
   发表时间:2010-09-18  
同意你的说法,开发效率主要取决于开发者对语言和平台的熟悉程度,所以我才说这篇文章面向web开发者嘛
反正我们公司要开发网站服务的objective-c客户端,我是持反对态度的,开发效率倒是小事,花钱也是小事,运营和推广才是重点,毕竟要推客户端,比仅仅推广一个网站要麻烦多了

对于要为自己的网站开发多触式版本的页面的朋友来说,我推荐单独为多触式设备设计体验和页面,而不是在现有页面的基础上重构,因为用鼠标和用手指是完全不同的两种体验

我在ipad上使用过flipboard这种专为多触式设备设计的体验后就不太喜欢上新浪这种传统资讯站了,虽然flipboard是native应用,但是个人感觉要用js + css + html实现一个差不多的东西出来并不是太难,有时间的话,过个把月大家就能看到一个雏形了
fkpwolf 写道
代价比用Objective-c重写高?不一定。如果你对HTML和JAVASCRIPT非常熟悉,可能是这样,如果跟我一样是个半吊子,要写出有吸引力的UI还是费功夫的。

尽量使用REST可能对UI的跨平台性有帮助,客户端也就演变成RIA了。

1 请登录后投票
   发表时间:2010-09-18  
苹果也大力推荐HTML5,感觉这个不是根自己的app store背道而驰么?想不明白
1 请登录后投票
   发表时间:2010-09-20  
http://www.frumtube.com/facebook/swipe7/
ipad上面支持flip,页面布局随方向变化,菜单隐藏,拖动
1 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics