JS怎樣實現(xiàn)移動端手勢操作 5種常見手勢識別與事件處理

移動端手勢操作可通過監(jiān)聽touch事件實現(xiàn),核心在于根據(jù)觸摸軌跡判斷手勢類型。1.滑動識別:記錄起始坐標,在touchend中計算deltax/deltay并比較閾值與方向;2.捏合識別:監(jiān)聽多點觸控,計算兩指距離變化以判斷放大或縮小;3.長按識別:設(shè)置定時器,在touchend或touchmove時清除定時器以判斷是否觸發(fā)長按;4.手勢沖突處理:通過優(yōu)先級判斷、使用手勢庫或自定義邏輯解決;5.hammer.JS簡化方案:引入庫后創(chuàng)建實例并注冊手勢事件,如swipe、pinch等,實現(xiàn)高效開發(fā)。

JS怎樣實現(xiàn)移動端手勢操作 5種常見手勢識別與事件處理

移動端手勢操作,說白了,就是讓你的網(wǎng)頁或應(yīng)用在手機上也能像原生應(yīng)用一樣,指哪打哪,體驗絲滑。JS來實現(xiàn),核心在于監(jiān)聽 touch 事件,然后根據(jù) touch 事件的軌跡來判斷用戶做了什么手勢。

JS怎樣實現(xiàn)移動端手勢操作 5種常見手勢識別與事件處理

解決方案

JS實現(xiàn)移動端手勢操作,主要圍繞 touchstart、touchmove、touchend 這三個事件。你需要監(jiān)聽這些事件,然后提取觸摸點的坐標,計算距離、速度、角度等信息,最后根據(jù)這些信息判斷手勢類型。

JS怎樣實現(xiàn)移動端手勢操作 5種常見手勢識別與事件處理

  1. touchstart: 記錄觸摸開始時的坐標。
  2. touchmove: 不斷記錄觸摸移動時的坐標,并計算與起始坐標的距離、方向等。
  3. touchend: 觸摸結(jié)束時,根據(jù)之前的記錄判斷手勢類型。

代碼示例 (簡化版):

JS怎樣實現(xiàn)移動端手勢操作 5種常見手勢識別與事件處理

let startX, startY;  document.addEventListener('touchstart', (e) => {   startX = e.touches[0].clientX;   startY = e.touches[0].clientY; });  document.addEventListener('touchend', (e) => {   const endX = e.changedTouches[0].clientX;   const endY = e.changedTouches[0].clientY;   const deltaX = endX - startX;   const deltaY = endY - startY;    // 簡單的左右滑動判斷   if (Math.abs(deltaX) > 50) {     if (deltaX > 0) {       console.log('向右滑動');     } else {       console.log('向左滑動');     }   } });

這個例子只是個最簡單的滑動判斷,實際應(yīng)用中需要更復(fù)雜的邏輯來處理各種手勢。

如何識別移動端常見的滑動(Swipe)手勢?

滑動是最常見的手勢之一,識別它的關(guān)鍵在于判斷觸摸點在水平或垂直方向上的移動距離是否超過一定的閾值。

步驟:

  1. 記錄起始坐標: 在 touchstart 事件中記錄起始坐標 startX 和 startY。
  2. 計算移動距離: 在 touchend 事件中,計算結(jié)束坐標 endX 和 endY 與起始坐標的差值 deltaX 和 deltaY。
  3. 判斷滑動方向和距離:
    • 計算 abs(deltaX) 和 abs(deltaY),判斷哪個方向的移動距離更大。
    • 如果 abs(deltaX) > threshold 且 abs(deltaX) > abs(deltaY),則認為是水平滑動。
    • 如果 abs(deltaY) > threshold 且 abs(deltaY) > abs(deltaX),則認為是垂直滑動。
    • 根據(jù) deltaX 和 deltaY 的正負號判斷滑動方向(左/右/上/下)。

代碼示例:

let startX, startY; const threshold = 50; // 滑動閾值  document.addEventListener('touchstart', (e) => {   startX = e.touches[0].clientX;   startY = e.touches[0].clientY; });  document.addEventListener('touchend', (e) => {   const endX = e.changedTouches[0].clientX;   const endY = e.changedTouches[0].clientY;   const deltaX = endX - startX;   const deltaY = endY - startY;    if (Math.abs(deltaX) > threshold && Math.abs(deltaX) > Math.abs(deltaY)) {     if (deltaX > 0) {       console.log('向右滑動');     } else {       console.log('向左滑動');     }   } else if (Math.abs(deltaY) > threshold && Math.abs(deltaY) > Math.abs(deltaX)) {     if (deltaY > 0) {       console.log('向下滑動');     } else {       console.log('向上滑動');     }   } });

如何識別移動端常見的捏合(Pinch)手勢?

捏合手勢通常用于縮放,需要同時監(jiān)聽兩個觸摸點。

步驟:

  1. 監(jiān)聽多點觸控: touchstart 事件中,e.touches.Length 如果大于等于2,則表示是多點觸控。
  2. 計算初始距離: 記錄兩個觸摸點的初始距離。
  3. 計算變化距離: 在 touchmove 事件中,不斷計算兩個觸摸點之間的距離,并與初始距離比較。
  4. 判斷縮放方向: 如果距離變大,則認為是放大;如果距離變小,則認為是縮小。

代碼示例:

let initialDistance;  document.addEventListener('touchstart', (e) => {   if (e.touches.length >= 2) {     const touch1 = e.touches[0];     const touch2 = e.touches[1];     initialDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);   } });  document.addEventListener('touchmove', (e) => {   if (e.touches.length >= 2) {     const touch1 = e.touches[0];     const touch2 = e.touches[1];     const currentDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);      const scale = currentDistance / initialDistance;      if (scale > 1) {       console.log('放大');     } else {       console.log('縮小');     }   } });

如何識別移動端常見的長按(Long Press)手勢?

長按手勢需要一個定時器來判斷用戶是否按壓足夠長的時間。

步驟:

  1. touchstart 事件: 記錄觸摸開始的時間。
  2. 設(shè)置定時器: 設(shè)置一個定時器,例如 500ms。
  3. touchend 事件: 如果在定時器觸發(fā)之前,用戶抬起了手指(觸發(fā)了 touchend 事件),則清除定時器,表示不是長按。
  4. 定時器觸發(fā): 如果定時器觸發(fā),則表示用戶長按了屏幕。

代碼示例:

let timer;  document.addEventListener('touchstart', (e) => {   timer = setTimeout(() => {     console.log('長按');   }, 500); // 500ms });  document.addEventListener('touchend', (e) => {   clearTimeout(timer); });  document.addEventListener('touchmove', (e) => {   clearTimeout(timer); // 移動時也清除定時器 });

如何處理移動端手勢沖突?

手勢沖突是指多個手勢同時發(fā)生或相互干擾的情況。例如,在縮放的同時進行拖動。

解決方案:

  1. 優(yōu)先級判斷: 根據(jù)應(yīng)用的需求,為不同的手勢設(shè)置優(yōu)先級。例如,縮放的優(yōu)先級高于拖動,則在縮放發(fā)生時,禁用拖動。
  2. 手勢識別庫: 使用現(xiàn)成的手勢識別庫,例如 Hammer.js,它們通常會處理一些常見的手勢沖突。
  3. 自定義邏輯: 根據(jù)具體情況,編寫自定義的邏輯來處理手勢沖突。例如,可以設(shè)置一個標志位,表示當前正在進行縮放操作,從而禁用其他手勢。
  4. preventDefault(): 在某些情況下,可以使用 e.preventDefault() 阻止默認行為,避免干擾手勢識別。例如,阻止?jié)L動條滾動,以便更好地識別滑動操作。

如何使用 Hammer.js 簡化手勢識別?

Hammer.js 是一個流行的 JavaScript 手勢識別庫,可以簡化移動端手勢識別的開發(fā)。

使用步驟:

  1. 引入 Hammer.js: 可以通過 CDN 或 npm 安裝 Hammer.js。
  2. 創(chuàng)建 Hammer 實例: 將需要監(jiān)聽手勢的 dom 元素傳遞給 Hammer 構(gòu)造函數(shù)。
  3. 注冊手勢: 使用 hammer.on() 方法注冊需要監(jiān)聽的手勢,并指定回調(diào)函數(shù)。

代碼示例:

<div id="myElement"></div> <script src="hammer.min.js"></script> <script>   const element = document.getElementById('myElement');   const hammer = new Hammer(element);    hammer.on('swipeleft', function(ev) {     console.log('向左滑動');   });    hammer.on('swiperight', function(ev) {     console.log('向右滑動');   });    hammer.on('pinch', function(ev) {     console.log('捏合');   }); </script>

Hammer.js 提供了許多內(nèi)置的手勢識別器,例如 tap、doubletap、press、swipe、pinch、rotate 等,并且可以自定義手勢識別器。 使用 Hammer.js 可以大大簡化手勢識別的代碼,提高開發(fā)效率。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊9 分享