Touch event 跟 mouse event 某程度上相當相似. 三個 event 分別是
touchstart, touchmove 及 touchend. 這就好比 mouse event 當中的 mousedown, mousemove 及 mouseup 三個 event.不過, touch event 跟 mouse event 的最大分別, 就是它本身設計支援 multi-touch, 所以每個 event handler 接收回來的 event 會包含每一隻手指(或接觸點)相關的資訊.
先拿
touchstart event 做例子:
document.getElementById('someid')
.addEventListener('touchstart', function(event){
var firstFinger = event.targetTouches[0];
document.getElementById('messageBox').innerHTML = 'point ' + firstFinger.pageX + ',' + firstFinger.pageY + ' touched!';
}, false);
以上例子不太實用, 不過旨在先提供一點概念. 首先留意到的, 是
event.targetTouches 是一個 array, 代表著接觸這個 DOM element 的每一隻手指. (另外還有 event.touches 代表所有手指, 以及 event.changedTouches 代表著跟這個 event 有關的所有手指, 這個稍後再說明)假設只會有 single touch 的情況下, 我可以直接抽起 array 之中的第一個項目使用. 在以上例子, 就當成是普通 mouse event 一樣, 利用
pageX 及 pageY 找出座標使用.touchmove 情況差不多, 就當手指在對應 DOM element 上移動時, touchmove event 就會包含每隻手指的位置. 舉個例:
document.getElementById('someid')
.addEventListener('touchmove', function(event){
var centroid = { x: 0, y: 0 };
for(var i=0; i<event.targetTouches.length; ++i) {
centroid.x += event.targetTouches[i].pageX;
centroid.y += event.targetTouches[i].pageY;
}
centroid.x /= event.targetTouches.length;
centroid.y /= event.targetTouches.length;
document.getElementById('messageBox').innerHTML =
'touch centroid: ' + centroid.x + ',' + centroid.y;
event.preventDefault();
}, false);
以上例子每當手指移動時, 就會計算出所有手指的中間位置然後顯示出來. 最主要的部份, 還是經過
event.targetTouches 這個 array 找出所有點然後處理. 使用
touchmove 時必須留意, 現時大部份 mobile browser 都會對應 touchmove 做 scrolling 效果, 尤其是當到達頁面盡頭時候的 bounch back 效果會影響到 touchmove event 的運作. 所以建議有需要時在最後加上 event.preventDefault() 去避免問題發生.最後到
touchend event, 使用方法就有點不同了:
document.getElementById('someid')
.addEventListener('touchend', function(event){
var touch = event.changedTouches[0];
document.getElementById('messageBox').innerHTML
= 'touch end: ' + touch.pageX + ',' + touch.pageY;
}, false);
由於當
touchend 發生之時手指已經離開螢幕, 所以要知道真正 trigger touchend event 的手指位置的話, 就要靠 event.changedTouches 了. 組合三個 event 就可以為網頁設計 gesture 了. 方法是利用
touchstart 記錄 gesture 的開始, 用 touchmove 去記錄軌跡, 最後在 touchend event 分析 gesture 並作出反應. 舉例說, 要處理 single touch gesture 的話, 可以這樣做:
var Touch = {
startPos: null,
endPos: null,
init: function(elementID) {
document.getElementById(elementID)
.addEventListener('touchstart',
function(event) { Touch.start(event); }, false);
document.getElementById(elementID)
.addEventListener('touchmove',
function(event) { Touch.update(event); }, false);
document.getElementById(elementID)
.addEventListener('touchend',
function(event) { Touch.stop(event); }, false);
},
start: function(event) {
var touch = event.targetTouches[0];
this.startPos = { x:touch.pageX, y:touch.pageY };
},
update: function(event) {
var touch = event.targetTouches[0];
// TODO: record gesture
},
stop: function(event) {
var touch = event.changedTouches[0];
this.endPos = { x:touch.pageX, y:touch.pageY };
var gesture = this.analyseGesture();
alert("The gesture is: " + gesture);
},
analyseGesture: function() {
if(this.startPos && this.endPos) {
if(this.endPos.x > this.startPos.x+200)
return "swipe right";
else if(this.endPos.x < this.startPos.x-200)
return "swipe left";
else
return "unknown";
}
}
};
以上例子很懶惰的只利用開始及結束的位置去估計是向左還是向右 swipe, 要更準確的話就要想一想應該在
touchmove 時記錄甚麼來分析了. 要使用這個例子的話, 可以把 Touch.init 加到 onload event 那裡:
window.onload = function() { Touch.init('someElementID'); };
(有關 Object function 在 event handler 上的應用, 可參考上一篇 令人又愛又恨的 JavaScript function :P)
可惜的是, 現時只有少部份軟件在 JavaScript touch event 之中支援 multi-touch, 期待將來 multi-touch 為 mobile web page 所帶來的更好的 user interface.
有關 touch event, 我推介 HTML5ROCKS 的相關介紹, 當中有提及更多 touch event 相關資料, 包括已定義但未有軟件支援的部份, 以及各主要軟硬件的支援情況, 做得相當不錯.
