觸摸操作概述
瀏覽器的觸摸 API 由三個部分組成。
- Touch:一個觸摸點
- TouchList:多個觸摸點的集合
- TouchEvent:觸摸引發(fā)的事件實例
Touch
接口的實例對象用來表示觸摸點(一根手指或者一根觸摸筆),包括位置、大小、形狀、壓力、目標元素等屬性。有時,觸摸動作由多個觸摸點(多根手指)組成,多個觸摸點的集合由TouchList
接口的實例對象表示。TouchEvent
接口的實例對象代表由觸摸引發(fā)的事件,只有觸摸屏才會引發(fā)這一類事件。
很多時候,觸摸事件和鼠標事件同時觸發(fā),即使這個時候并沒有用到鼠標。這是為了讓那些只定義鼠標事件、沒有定義觸摸事件的代碼,在觸摸屏的情況下仍然能用。如果想避免這種情況,可以用event.preventDefault
方法阻止發(fā)出鼠標事件。
Touch 接口
Touch 接口概述
Touch 接口代表單個觸摸點。觸摸點可能是一根手指,也可能是一根觸摸筆。
瀏覽器原生提供Touch
構造函數(shù),用來生成Touch
實例。
var touch = new Touch(touchOptions);
Touch
構造函數(shù)接受一個配置對象作為參數(shù),它有以下屬性。
identifier
:必需,類型為整數(shù),表示觸摸點的唯一 ID。target
:必需,類型為元素節(jié)點,表示觸摸點開始時所在的網(wǎng)頁元素。clientX
:可選,類型為數(shù)值,表示觸摸點相對于瀏覽器窗口左上角的水平距離,默認為0。clientY
:可選,類型為數(shù)值,表示觸摸點相對于瀏覽器窗口左上角的垂直距離,默認為0。screenX
:可選,類型為數(shù)值,表示觸摸點相對于屏幕左上角的水平距離,默認為0。screenY
:可選,類型為數(shù)值,表示觸摸點相對于屏幕左上角的垂直距離,默認為0。pageX
:可選,類型為數(shù)值,表示觸摸點相對于網(wǎng)頁左上角的水平位置(即包括頁面的滾動距離),默認為0。pageY
:可選,類型為數(shù)值,表示觸摸點相對于網(wǎng)頁左上角的垂直位置(即包括頁面的滾動距離),默認為0。radiusX
:可選,類型為數(shù)值,表示觸摸點周圍受到影響的橢圓范圍的 X 軸半徑,默認為0。radiusY
:可選:類型為數(shù)值,表示觸摸點周圍受到影響的橢圓范圍的 Y 軸半徑,默認為0。rotationAngle
:可選,類型為數(shù)值,表示觸摸區(qū)域的橢圓的旋轉角度,單位為度數(shù),在0到90度之間,默認值為0。force
:可選,類型為數(shù)值,范圍在0
到1
之間,表示觸摸壓力。0
代表沒有壓力,1
代表硬件所能識別的最大壓力,默認為0
。
Touch 接口的實例屬性
(1)Touch.identifier
Touch.identifier
屬性返回一個整數(shù),表示觸摸點的唯一 ID。這個值在整個觸摸過程保持不變,直到觸摸事件結束。
someElement.addEventListener('touchmove', function (e) {
for (var i = 0; i < e.changedTouches.length; i++) {
console.log(e.changedTouches[i].identifier);
}
}, false);
(2)Touch.screenX,Touch.screenY,Touch.clientX,Touch.clientY,pageX,pageY
Touch.screenX
屬性和Touch.screenY
屬性,分別表示觸摸點相對于屏幕左上角的橫坐標和縱坐標,與頁面是否滾動無關。
Touch.clientX
屬性和Touch.clientY
屬性,分別表示觸摸點相對于瀏覽器視口左上角的橫坐標和縱坐標,與頁面是否滾動無關。
Touch.pageX
屬性和Touch.pageY
屬性,分別表示觸摸點相對于當前頁面左上角的橫坐標和縱坐標,包含了頁面滾動帶來的位移。
(3)Touch.radiusX,Touch.radiusY,Touch.rotationAngle
Touch.radiusX
屬性和Touch.radiusY
屬性,分別返回觸摸點周圍受到影響的橢圓范圍的 X 軸半徑和 Y 軸半徑,單位為像素。乘以 2 就可以得到觸摸范圍的寬度和高度。
Touch.rotationAngle
屬性表示觸摸區(qū)域的橢圓的旋轉角度,單位為度數(shù),在0
到90
度之間。
上面這三個屬性共同定義了用戶與屏幕接觸的區(qū)域,對于描述手指這一類非精確的觸摸,很有幫助。指尖接觸屏幕,觸摸范圍會形成一個橢圓,這三個屬性就用來描述這個橢圓區(qū)域。
下面是一個示例。
div.addEventListener('touchstart', rotate);
div.addEventListener('touchmove', rotate);
div.addEventListener('touchend', rotate);
function rotate(e) {
var touch = e.changedTouches.item(0);
e.preventDefault();
src.style.width = touch.radiusX * 2 + 'px';
src.style.height = touch.radiusY * 2 + 'px';
src.style.transform = 'rotate(' + touch.rotationAngle + 'deg)';
};
(4)Touch.force
Touch.force
屬性返回一個0
到1
之間的數(shù)值,表示觸摸壓力。0
代表沒有壓力,1
代表硬件所能識別的最大壓力。
(5)Touch.target
Touch.target
屬性返回一個元素節(jié)點,代表觸摸發(fā)生時所在的那個元素節(jié)點。即使觸摸點已經(jīng)離開了這個節(jié)點,該屬性依然不變。
TouchList 接口
TouchList
接口表示一組觸摸點的集合。它的實例是一個類似數(shù)組的對象,成員是Touch
的實例對象,表示所有觸摸點。用戶用三根手指觸摸,產(chǎn)生的TouchList
實例就會包含三個成員,每根手指的觸摸點對應一個Touch
實例對象。
它的實例主要通過觸摸事件的TouchEvent.touches
、TouchEvent.changedTouches
、TouchEvent.targetTouches
這幾個屬性獲取。
它的實例屬性和實例方法只有兩個。
TouchList.length
:數(shù)值,表示成員數(shù)量(即觸摸點的數(shù)量)。TouchList.item()
:返回指定位置的成員,它的參數(shù)是該成員的位置編號(從零開始)。
TouchEvent 接口
概述
TouchEvent 接口繼承了 Event 接口,表示由觸摸引發(fā)的事件實例,通常來自觸摸屏或軌跡板。除了被繼承的屬性以外,它還有一些自己的屬性。
瀏覽器原生提供TouchEvent()
構造函數(shù),用來生成觸摸事件的實例。
new TouchEvent(type, options)
TouchEvent()
構造函數(shù)可以接受兩個參數(shù),第一個參數(shù)是字符串,表示事件類型;第二個參數(shù)是事件的配置對象,該參數(shù)是可選的,對象的所有屬性也是可選的。除了Event
接口的配置屬性,該接口還有一些自己的配置屬性。
touches
:TouchList
實例,代表所有的當前處于活躍狀態(tài)的觸摸點,默認值是一個空數(shù)組[]
。targetTouches
:TouchList
實例,代表所有處在觸摸的目標元素節(jié)點內(nèi)部、且仍然處于活動狀態(tài)的觸摸點,默認值是一個空數(shù)組[]
。changedTouches
:TouchList
實例,代表本次觸摸事件的相關觸摸點,默認值是一個空數(shù)組[]
。ctrlKey
:布爾值,表示 Ctrl 鍵是否同時按下,默認值為false
。shiftKey
:布爾值,表示 Shift 鍵是否同時按下,默認值為false
。altKey
:布爾值,表示 Alt 鍵是否同時按下,默認值為false
。metaKey
:布爾值,表示 Meta 鍵(或 Windows 鍵)是否同時按下,默認值為false
。
實例屬性
TouchEvent 接口的實例具有Event
實例的所有屬性和方法,此外還有一些它自己的實例屬性,這些屬性全部都是只讀。
(1)TouchEvent.altKey,TouchEvent.ctrlKey,TouchEvent.shiftKey,TouchEvent.metaKey
TouchEvent.altKey
:布爾值,表示觸摸時是否按下了 Alt 鍵。TouchEvent.ctrlKey
:布爾值,表示觸摸時是否按下了 Ctrl 鍵。TouchEvent.shiftKey
:布爾值:表示觸摸時是否按下了 Shift 鍵。TouchEvent.metaKey
:布爾值,表示觸摸時是否按下了 Meta 鍵(或 Windows 鍵)。
下面是一個示例。
someElement.addEventListener('touchstart', function (e) {
console.log('altKey = ' + e.altKey);
console.log('ctrlKey = ' + e.ctrlKey);
console.log('metaKey = ' + e.metaKey);
console.log('shiftKey = ' + e.shiftKey);
}, false);
(2)TouchEvent.changedTouches
TouchEvent.changedTouches
屬性返回一個TouchList
實例,成員是一組Touch
實例對象,表示本次觸摸事件的相關觸摸點。
對于不同的時間,該屬性的含義有所不同。
touchstart
事件:被激活的觸摸點touchmove
事件:發(fā)生變化的觸摸點touchend
事件:消失的觸摸點(即不再被觸碰的點)
下面是一個示例。
someElement.addEventListener('touchmove', function (e) {
for (var i = 0; i < e.changedTouches.length; i++) {
console.log(e.changedTouches[i].identifier);
}
}, false);
(3)TouchEvent.touches
TouchEvent.touches
屬性返回一個TouchList
實例,成員是所有仍然處于活動狀態(tài)(即觸摸中)的觸摸點。一般來說,一個手指就是一個觸摸點。
下面是一個示例。
someElement.addEventListener('touchstart', function (e) {
switch (e.touches.length) {
// 一根手指觸摸
case 1: handle_one_touch(e); break;
// 兩根手指觸摸
case 2: handle_two_touches(e); break;
// 三根手指觸摸
case 3: handle_three_touches(e); break;
// 其他情況
default: console.log('Not supported'); break;
}
}, false);
(4)TouchEvent.targetTouches
TouchEvent.targetTouches
屬性返回一個TouchList
實例,成員是觸摸事件的目標元素節(jié)點內(nèi)部、所有仍然處于活動狀態(tài)(即觸摸中)的觸摸點。
function touches_in_target(ev) {
return (ev.touches.length === ev.targetTouches.length ? true : false);
}
上面代碼用來判斷,是否所有觸摸點都在目標元素內(nèi)。
觸摸事件的種類
觸摸引發(fā)的事件,有以下幾種??梢酝ㄟ^TouchEvent.type
屬性,查看到底發(fā)生的是哪一種事件。
touchstart
:用戶開始觸摸時觸發(fā),它的target
屬性返回發(fā)生觸摸的元素節(jié)點。touchend
:用戶不再接觸觸摸屏時(或者移出屏幕邊緣時)觸發(fā),它的target
屬性與touchstart
事件一致的,就是開始觸摸時所在的元素節(jié)點。它的changedTouches
屬性返回一個TouchList
實例,包含所有不再觸摸的觸摸點(即Touch
實例對象)。touchmove
:用戶移動觸摸點時觸發(fā),它的target
屬性與touchstart
事件一致。如果觸摸的半徑、角度、力度發(fā)生變化,也會觸發(fā)該事件。touchcancel
:觸摸點取消時觸發(fā),比如在觸摸區(qū)域跳出一個模態(tài)窗口(modal window)、觸摸點離開了文檔區(qū)域(進入瀏覽器菜單欄)、用戶的觸摸點太多,超過了支持的上限(自動取消早先的觸摸點)。
下面是一個例子。
var el = document.getElementsByTagName('canvas')[0];
el.addEventListener('touchstart', handleStart, false);
el.addEventListener('touchmove', handleMove, false);
function handleStart(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
for (var i = 0; i < touches.length; i++) {
console.log(touches[i].pageX, touches[i].pageY);
}
}
function handleMove(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
for (var i = 0; i < touches.length; i++) {
var touch = touches[i];
console.log(touch.pageX, touch.pageY);
}
}
更多建議: