JavaScript 觸摸事件

2023-03-20 15:46 更新

觸摸操作概述

瀏覽器的觸摸 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ù)值,范圍在01之間,表示觸摸壓力。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ù),在090度之間。

上面這三個(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è)01之間的數(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接口的配置屬性,該接口還有一些自己的配置屬性。

  • touchesTouchList實(shí)例,代表所有的當(dāng)前處于活躍狀態(tài)的觸摸點(diǎn),默認(rèn)值是一個(gè)空數(shù)組[]。
  • targetTouchesTouchList實(shí)例,代表所有處在觸摸的目標(biāo)元素節(jié)點(diǎn)內(nèi)部、且仍然處于活動(dòng)狀態(tài)的觸摸點(diǎn),默認(rèn)值是一個(gè)空數(shù)組[]
  • changedTouchesTouchList實(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);
  }
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)