js的touch事件,一般用於行動端的觸控螢幕滑動
touchstart:當手指觸摸螢幕時觸發;即使已經有一個手指放在了螢幕上也會觸發。
touchmove:當手指在螢幕上滑動時連續的觸發。在這個事件發生期間,呼叫preventDefault()可阻止捲動。
touchend:當手指從螢幕上移開時觸發。
touchcancel:當系統停止追蹤觸控時觸發。關於此事件的確切觸發事件,文件中沒有明確說明。
以上事件的event物件上面都存在如下屬性:
touches:表示目前追蹤的觸控操作的Touch物件的陣列。
targetTouches:特定於事件目標的Touch物件的陣列。
changeTouches:表示自上次觸碰以來發生了什麼改變的Touch物件的陣列。
每個Touch物件包含下列屬性:
clientX:觸碰目標在視窗中的X座標。
clientY:觸碰目標在視窗中的Y座標。
identifier:表示觸碰的唯一ID。
pageX:觸碰目標在頁面中的x座標。
pageY:觸碰目標在頁面中的y座標。
screenX:觸碰目標在螢幕中的x座標。
screenY:觸碰目標在螢幕中的y座標。
target:觸摸的DOM節點座標
觸控事件
三種在規格中列出並獲得跨行動裝置廣泛實現的基本觸控事件:
1. touchstart:手指放在一個DOM元素上。
2. touchmove:手指拖曳一個DOM元素。
3. touchend:手指從一個DOM元素移開。
每個觸控事件都包含了三個觸控清單:
1. touches:目前位於螢幕上的所有手指的清單。
2. targetTouches:位於目前DOM元素上的手指的清單。
3. changedTouches:涉及目前事件的手指的一個清單
例如,在一個touchend事件中,這就會是移開的手指。
這些清單由包含了觸控資訊的物件組成:
1. identifier:一個數值,唯一標識觸控會話(touch session)中的目前手指。
2. target:DOM元素,是動作所針對的目標。
3. 顧客/頁面/螢幕座標:螢幕上動作發生的位置。
4. 半徑座標與 rotationAngle:畫出約相當於手指形狀的橢圓形。
可觸控應用
touchstart、touchmove和touchend事件提供了一組足夠豐富的功能來支援幾乎是任何類型的基於觸控的互動——其中包括常見的多點觸控手勢,比如說捏縮放、旋轉等待。 下面的這段程式碼讓你用單指觸控來四處拖曳一個DOM元素:
var obj = document.getElementByIdx_x_x_x_x_x_x('id'); obj.addEventListener('touchmove', function(event) { // 如果这个元素的位置内只有一个手指的话 if (event.targetTouches.length == 1) { var touch = event.targetTouches[0]; // 把元素放在手指所在的位置 obj.style.left = touch.pageX + 'px'; obj.style.top = touch.pageY + 'px'; } }, false);
以下有一個範例,此範例顯示了螢幕上目前所有的接點,而它的功能就是用來感受一下裝置的反應性。
// 设置画布并通过ctx变量来暴露上下文复制代码 canvas.addEventListener('touchmove', function(event) { for (var i = 0; i < event.touches.length; i++) { var touch = event.touches; ctx.beginPath(); ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true); ctx.fill(); ctx.stroke(); } }, false);
示範
到處都有許多有趣的多點觸控演示,比如說這個由Paul Irish和其他人實現的基於畫布的繪畫演示。
還有Browser Ninja,技術演示,是使用了CSS3的轉換、過渡和畫布的Fruit Ninja克隆。
最佳做法
阻止縮放
缺省的多點觸控設定不是特別的好用,因為你的滑動和手勢往往與瀏覽器的行為有關聯,比如說滾動和縮放。
要停用縮放功能的話,使用下面的元標記設定你的視圖區(viewport),這樣其對使用者來說就是不可伸縮的了:
content="width=device-width, initial-scale=1.0, user-scalable=no">
看看這篇關於行動HTML 5的文章,以了解更多關於檢視區設定的資訊。
阻止滾動
有些行動裝置有缺省的touchmove行為,比如說經典的iOS overscroll效果,當滾動超出了內容的界限時就引發視圖反彈。這種做法在許多多點觸控應用中會帶來混亂,但要停用它很容易。
document.body.addEventListener('touchmove', function(event) { event.preventDefault(); }, false);
细心渲染
如果你正在编写的多点触控应用涉及了复杂的多指手势的话,要小心地考虑如何响应触摸事件,因为一次要处理这么多的事情。考虑一下前面一节中的在屏幕上画出所有触点的例子,你可以在有触摸输入的时候就立刻进行绘制:
canvas.addEventListener('touchmove', function(event) { renderTouches(event.touches); },
不过这一技术并不是要随着屏幕上的手指个数的增多而扩充,替代做法是,可以跟踪所有的手指,然后在一个循环中做渲染,这样可获得更好的性能:
var touches = [] canvas.addEventListener('touchmove', function(event) { touches = event.touches; }, false); // 设置一个每秒60帧的定时器 timer = setInterval(function() { renderTouches(touches); }, 15);
提示:setInterval不太适合于动画,因为它没有考虑到浏览器自己的渲染循环。现代的桌面浏览器提供了requestAnimationFrame这一函数,基于性能和电池工作时间原因,这是一个更好的选择。一但浏览器提供了对该函数的支持,那将是首选的处理事情的方式。
使用targetTouches和changedTouches
要记住的一点是,event.touches是与屏幕接触的所有手指的一个数组,而不仅是位于目标DOM元素上的那些。你可能会发现使用 event.targetTouches和event.changedTouches来代替event.touches更有用一些。
最后一点,因为你是在为移动设备做开发,因此你应该要留心移动的最佳做法,这些在Eric Bidelman的文章中有论及,以及要了解这一W3C文档。
设备支持
遗憾的是,触摸事件的实现在完备性和质量方面的差别很大。我编写了一个诊断脚本来显示一些关于触摸API实现的基本信息,其中包括哪些事件是支持的,以及 touchmove事件触发的解决方案。我在Nexus One和Nexus S硬件上测试了Android2.3.3,在Xoom上测试了Android 3.0.1,以及在iPad和iPhone上测试了iOS 4.2。
简而言之,所有被测试的浏览器都支持touchstart、touchend和touchmove事件。
规范提供了额外的三个触摸事件,但被测试的浏览器没有支持它们:
1. touchenter:移动的手指进入一个DOM元素。
2. toucheleave:移动手指离开一个DOM元素。
3. touchcancel:触摸被中断(实现规范)。
被测试的浏览器还在每个触摸列表内部都提供了touches、targetTouches和changedTouches列表。不过,被测试的浏览器没有支持radiusX、radiusY或是rotationAngle属性,这些属性指明触摸屏幕的手指的形状。在一次touchmove期间,事件大约一秒钟触发60次,所有的被测试设备都是这样。