用 TypeScript 開發手勢庫 - (1)web開發常用手勢有哪些?

鐵皮飯盒發表於2019-03-18

這只是個開頭

說在最前面,本文是一個系列文章的開頭, 這個系列裡我會講如何用typescript開發一款支援pc手機端的手勢庫any-touch, 以及通過jest讓你的程式碼測試覆蓋率100%.

https://github.com/383514580/any-touch

往期目錄

用 TypeScript 開發手勢庫 - (2)web開發常用手勢有哪些?

用 TypeScript 開發手勢庫 - (3)統一化Mouse和Touch事件

不到30行, 用any-touch實現一個drawer

今天我們先不寫程式碼

今天的文章裡我們先不講程式碼, 我們講一下都有哪些手勢以及手勢的邏輯, 理解了邏輯再寫程式碼就簡單了.

感謝一定要寫在最前面

  1. 感謝開源的hammer.js, 是他讓我學會了很多手勢方面的知識.

  2. 還要感謝寫這篇文章的作者,文章地址, 文章詳細介紹了關於旋轉和縮放手勢變化的計算.

那麼常用手勢有哪些?

回到正題, 常見的手勢有: tap(點選) \ press(按住) \ 拖拽(pan) \ 劃過(swipe) \ 捏合縮放(pinch) \ 旋轉(rotate), 所有的手勢在移動端其實都是通過touch事件的不同觸發時機而區分出的(pc端是mouseup/mousemove/mousedown, 關於如何通過滑鼠識別手勢, 後面的文章會有單獨的章節).

這裡有個demo, 我把所有的手勢識別放在了裡面.

tap(點選)

眾所周知, 移動端的click有300ms延遲(瀏覽器延遲300ms為了識別雙擊操作, 因為移動端瀏覽器預設雙擊可以縮放頁面), 為了避免"點選穿透"我們建立了tap事件, 同時通過preventDefault來禁止click觸發. tap在touchend階段觸發, 說下識別tap的必要條件:

  1. 觸發一次touchstart和touchend.
  2. touchstart和touchend的座標之間的距離不能超過2px.
  3. touchstart觸發後,250ms內必須觸發touchend, 不然會被識別成press.

doubletap(雙擊)

2次連續的tap(單擊)觸發雙擊, 雙擊的原理如下: 每次tap後並不觸發tap, 而是等待300ms看是否有雙擊觸發, 如果沒有那麼2次tap依次觸發, 否則觸發雙擊,單擊不觸發. (關於多擊更細的原理, 後面我會單獨通過原始碼解析), 必要條件:

  1. 2次點選之間不能超過300ms.
  2. 2次點選的距離不能超過9px.

press(按)

按住螢幕不放, 一段時間後觸發press時間,觸發press後, 離開觸點, 觸發pressup事件, 識別的必要條件如下:

  1. touchstart和touchmove之間的距離不能超過9px.
  2. 即便觸點不離開螢幕, 251ms後也會觸發press. 這個251ms對應tap的必要條件第3條.

pan(拖拽)

(1指或多指)按住螢幕不離開, 每一次移動都會觸發pan. 舉幾個例子:

  1. 輪播效果的拖拽切換, 這個拖拽動作就是pan.
  2. 抽屜(draw)元件的拖拽顯示更多內容.
  3. 選項卡(tabs)元件的拖拽顯示更多選項卡. pan是元件開發中最常用的手勢.

swipe(劃)

(1指或多指)按住螢幕快速滑動, 當手指離開螢幕的一瞬間, 觸發swipe. 必要條件如下:

  1. 滑動超過一定距離(如10px).
  2. 滑動速度足夠快(大於0.3px/ms). 輪播元件的用swipe來表示"切換下一幕".

pinch(齧合)

2指及以上按住螢幕, 讓2個手指之間的距離發生變化, 通過距離的變化來表示pinch是放大開始縮小. 常見於gallery元件, 用來放大/縮小圖片.

rotate(旋轉)

2指及以上按住螢幕, 通過2指連線形成的直線和座標系的x軸的夾角的變化而觸發rotate. 常用於圖片處理, 用來旋轉圖片.

原始碼

上面關於手勢識別的具體邏輯可以看我的倉庫, 地址: github.com/383514580/a…

未完待續

本次先講這麼多, 後面的文章具體要講什麼看大家的回覆想聽什麼, 期待大家的回覆, 本人熱愛前端, 但能力有限, 有講的不對的請大家多多指點.

相關概念解釋

點選穿透

當A/B兩個層上下z軸重疊,上層的A點選後消失或移開,並且B元素本身有預設click事件(如a標籤)或繫結了click事件。在這種情況下,點選A/B重疊的部分,就會出現點透的現象.

相關文章