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