js怎樣實(shí)現(xiàn)手勢(shì)識(shí)別功能 移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案

移動(dòng)端手勢(shì)識(shí)別可通過四種方案實(shí)現(xiàn)。1.原生touch事件,靈活但代碼量大且需處理兼容性;2.hammer.JS庫使用簡單但增加體積;3.pointer events api標(biāo)準(zhǔn)化但兼容性差;4.web components封裝組件化邏輯。選擇時(shí)應(yīng)根據(jù)項(xiàng)目復(fù)雜度、性能、兼容性及開發(fā)效率權(quán)衡。優(yōu)化性能可通過減少監(jiān)聽、使用requestanimationframe、節(jié)流和避免線程阻塞。處理沖突可stoppropagation、preventdefault或定義優(yōu)先級(jí)。測試應(yīng)結(jié)合真機(jī)、模擬器和單元測試。

js怎樣實(shí)現(xiàn)手勢(shì)識(shí)別功能 移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案

移動(dòng)端手勢(shì)識(shí)別,簡單來說,就是讓你的 JavaScript 代碼能“看懂”用戶在屏幕上劃拉、捏合等動(dòng)作,并根據(jù)這些動(dòng)作做出相應(yīng)的反應(yīng)。實(shí)現(xiàn)方式有很多,但目標(biāo)都是讓你的 Web 應(yīng)用或混合應(yīng)用更具交互性。

js怎樣實(shí)現(xiàn)手勢(shì)識(shí)別功能 移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案

js實(shí)現(xiàn)手勢(shì)識(shí)別功能,移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案:

js怎樣實(shí)現(xiàn)手勢(shì)識(shí)別功能 移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案

方案一:原生 touch 事件

這是最基礎(chǔ)的方式,直接監(jiān)聽 touchstart、touchmove、touchend 和 touchcancel 這四個(gè) touch 事件。你需要自己計(jì)算手指移動(dòng)的距離、方向、速度等,然后判斷是什么手勢(shì)。

js怎樣實(shí)現(xiàn)手勢(shì)識(shí)別功能 移動(dòng)端手勢(shì)識(shí)別的4種實(shí)現(xiàn)方案

優(yōu)點(diǎn): 靈活,完全掌控,可以實(shí)現(xiàn)各種復(fù)雜的手勢(shì)。

缺點(diǎn): 代碼量大,需要處理各種邊界情況,容易出錯(cuò),兼容性問題也需要考慮。例如,不同設(shè)備的 touch 事件坐標(biāo)可能存在差異。

示例代碼:

let startX, startY;  document.addEventListener('touchstart', (e) => {   startX = e.touches[0].clientX;   startY = e.touches[0].clientY; });  document.addEventListener('touchmove', (e) => {   const x = e.touches[0].clientX;   const y = e.touches[0].clientY;   const deltaX = x - startX;   const deltaY = y - startY;    // 根據(jù) deltaX 和 deltaY 判斷手勢(shì)方向   if (Math.abs(deltaX) > Math.abs(deltaY)) {     if (deltaX > 0) {       console.log('向右滑動(dòng)');     } else {       console.log('向左滑動(dòng)');     }   } else {     if (deltaY > 0) {       console.log('向下滑動(dòng)');     } else {       console.log('向上滑動(dòng)');     }   } });  document.addEventListener('touchend', (e) => {   // 處理 touchend 事件 });

方案二:使用 Hammer.js

Hammer.js 是一個(gè)流行的手勢(shì)識(shí)別庫,它封裝了 touch 事件的處理,提供了更高級(jí)的手勢(shì)識(shí)別功能,例如 swipe、pinch、rotate 等。

優(yōu)點(diǎn): 使用簡單,功能強(qiáng)大,跨平臺(tái)兼容性好。

缺點(diǎn): 引入第三方庫,會(huì)增加項(xiàng)目體積。

示例代碼:

const element = document.getElementById('myElement'); const hammer = new Hammer(element);  hammer.on('swipeleft', function(ev) {   console.log('向左滑動(dòng)'); });  hammer.on('swiperight', function(ev) {   console.log('向右滑動(dòng)'); });  hammer.get('pinch').set({ enable: true }); hammer.get('rotate').set({ enable: true });  hammer.on("pinch", function(ev) {   console.log(ev.scale); // 縮放比例 });  hammer.on("rotate", function(ev) {   console.log(ev.rotation); // 旋轉(zhuǎn)角度 });

方案三:使用 Pointer Events API

Pointer Events API 是 W3C 標(biāo)準(zhǔn),旨在統(tǒng)一處理鼠標(biāo)、觸摸和筆等輸入設(shè)備。相比 touch 事件,它更通用,也更易于使用。

優(yōu)點(diǎn): 標(biāo)準(zhǔn)化,易于使用,可以處理多種輸入設(shè)備。

缺點(diǎn): 兼容性不如 touch 事件好,需要 polyfill。

示例代碼:

element.addEventListener('pointerdown', (e) => {   // 處理 pointerdown 事件 });  element.addEventListener('pointermove', (e) => {   // 處理 pointermove 事件 });  element.addEventListener('pointerup', (e) => {   // 處理 pointerup 事件 });

方案四:使用 Web Components

可以封裝一個(gè) Web Component,將手勢(shì)識(shí)別的邏輯封裝在組件內(nèi)部,對(duì)外提供簡單的 API。

優(yōu)點(diǎn): 組件化,易于復(fù)用,代碼結(jié)構(gòu)清晰。

缺點(diǎn): 需要學(xué)習(xí) Web Components 的相關(guān)知識(shí)。

示例代碼:

class GestureRecognizer extends HTMLElement {   constructor() {     super();     this.attachShadow({ mode: 'open' });     this.shadowRoot.innerHTML = `       <style>         :host {           display: block;         }       </style>       <div><slot></slot></div>     `;      this.startX = 0;     this.startY = 0;      this.addEventListener('touchstart', this._handleTouchStart);     this.addEventListener('touchmove', this._handleTouchMove);     this.addEventListener('touchend', this._handleTouchEnd);   }    _handleTouchStart(e) {     this.startX = e.touches[0].clientX;     this.startY = e.touches[0].clientY;   }    _handleTouchMove(e) {     const x = e.touches[0].clientX;     const y = e.touches[0].clientY;     const deltaX = x - this.startX;     const deltaY = y - this.startY;      // 根據(jù) deltaX 和 deltaY 判斷手勢(shì)方向     if (Math.abs(deltaX) > Math.abs(deltaY)) {       if (deltaX > 0) {         this.dispatchEvent(new CustomEvent('swipeRight'));       } else {         this.dispatchEvent(new CustomEvent('swipeLeft'));       }     } else {       if (deltaY > 0) {         this.dispatchEvent(new CustomEvent('swipeDown'));       } else {         this.dispatchEvent(new CustomEvent('swipeUp'));       }     }   }    _handleTouchEnd(e) {     // 處理 touchend 事件   } }  customElements.define('gesture-recognizer', GestureRecognizer);

使用:

<gesture-recognizer id="myGestureElement">   <div>This is the content</div> </gesture-recognizer>  <script>   const gestureElement = document.getElementById('myGestureElement');   gestureElement.addEventListener('swipeLeft', () => {     console.log('Gesture: Swipe Left detected on Web Component!');   }); </script>

如何選擇合適的手勢(shì)識(shí)別方案?

  • 項(xiàng)目復(fù)雜度: 如果項(xiàng)目只需要簡單的手勢(shì)識(shí)別,例如 swipe,可以使用 Hammer.js 或 Pointer Events API。如果需要實(shí)現(xiàn)復(fù)雜的手勢(shì),例如自定義手勢(shì),建議使用原生 touch 事件。
  • 性能要求: 原生 touch 事件的性能最高,但需要自己優(yōu)化。Hammer.js 的性能也不錯(cuò),但需要注意配置,避免不必要的手勢(shì)識(shí)別。
  • 兼容性要求: touch 事件的兼容性最好,Pointer Events API 需要 polyfill。
  • 開發(fā)效率: Hammer.js 和 Web Components 可以提高開發(fā)效率。

如何優(yōu)化手勢(shì)識(shí)別的性能?

  • 減少事件監(jiān)聽: 只監(jiān)聽需要的手勢(shì)事件。
  • 使用 requestAnimationFrame: 在 touchmove 事件中,使用 requestAnimationFrame 來更新 ui,避免卡頓。
  • 節(jié)流: 對(duì) touchmove 事件進(jìn)行節(jié)流,避免頻繁計(jì)算。
  • 避免阻塞主線程: 將耗時(shí)的計(jì)算放在 Web Worker 中進(jìn)行。

如何處理手勢(shì)沖突?

  • stopPropagation: 阻止事件冒泡,避免父元素也響應(yīng)手勢(shì)。
  • preventDefault: 阻止默認(rèn)行為,例如滾動(dòng)。
  • 使用手勢(shì)優(yōu)先級(jí): 定義手勢(shì)的優(yōu)先級(jí),優(yōu)先處理優(yōu)先級(jí)高的手勢(shì)。

如何測試手勢(shì)識(shí)別功能?

  • 使用真機(jī)測試: 模擬真實(shí)用戶的手勢(shì)操作。
  • 使用模擬器測試: 使用 chrome DevTools 的模擬器來模擬 touch 事件。
  • 編寫單元測試: 針對(duì)手勢(shì)識(shí)別的邏輯編寫單元測試。

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