AlloyFinger web 手勢學習

從 [長按] 開始學習 web 手勢

在項目開發過程當中遇到有虛擬鍵盤開發的需求(以下圖),其中刪除鍵須要實現 長按 刪除輸入框所有內容,由此展開今天要討論的 web 手勢 開發內容。git

線下掃碼

先放出實現代碼:github

var $input = document.getElementById('input');
var $delBtn = document.getElementById('delBtn');
var delBtnClock = null;
$delBtn.ontouchstart = function () {
    $input.innerHTML = $input.innerHTML.slice(0, -1)
    delBtnClock = setTimeout(function () {
        $input.innerHTML = '';
    }, 500);
}
$delBtn.ontouchend = function () {
    clearTimeout(delBtnClock);
    delBtnClock = null;
}

關鍵代碼就兩句話:web

  1. 在 touchstart 事件中開啓計時,這裏是計時 500 ms 後,刪除輸入框內容
  2. 在 touchend 事件中清除 setTimeout 計時器

若是隻是點擊,此時 touchend 距離 touchstart 確定不到 500 ms,計時器在時間沒到前已被刪除,實現的效果就只是退格;若是長按超過 500 ms,計時器執行,實現輸入框內容所有刪除。異步

因此 長按 手勢其實是由 touchstart & touchend & setTimeout 三者共同模擬的效果。學習

實際上,常規的 js 事件只支持 click、touchstart、touchend、touchmove、touchcancel 這五種與點擊相關的事件,若是想實現更多的諸如旋轉、放大縮小之類的手勢的話,就須要結合上面的五種事件和其餘方法來模擬實現了。spa

下面我未來介紹下傳說中的《超級小的 web 手勢庫:AlloyFinger》線程

學習 AlloyFinger

業內知名的強大的 web 手勢庫 hammer.js,總共有 3240 行代碼,壓縮版的 44.7 kb。與之相比,AlloyFinger 真的稱得上超級小了,326 行代碼,10 倍的差距,在 「kb 必爭」 移動 web 應用裏,AlloyFinger 一下就引發了廣大開發者的注意,代碼量小,功能又齊全,你還要什麼單車呢。(我是否是得找人家要下廣告費)code

在 AlloyFinger 裏,手勢一共有 14 種,除了常規的 4 種 touchstart,touchmove,touchend 和 touchcancel,還有 10 種由以上 4 種衍生出來的手勢以下:生命週期

  • multipointStart:多點開始
  • multipointEnd:多點結束
  • tap:點擊,效果如 click
  • doubleTap:雙擊
  • longTap:長按
  • singleTap:單擊狀況下 250 ms 內沒有再次點擊(會同時觸發 tap,tap 在前)
  • rotate:旋轉(同時觸發 pressMove)
  • pinch:放大縮小
  • pressMove:單點移動
  • twoFingerPressMove:多點移動
  • swipe:掃滑,在 touchend 裏觸發,與 touchmove 稍有不一樣

原理

  1. multipointStart

    touchstart 中,觸點多於 1 個時觸發事件

  2. multipointEnd

    touchend 中,觸點少於 2 個時觸發(一開始還在想是否是 bug,實際的意思是:最後一個手指離開時觸發)

  3. tap

    touchend 中,觸點沒有移動(移動橫縱距離小於 30 px),且沒有觸發 longTap 時(距離 touchStart 時間少於 750 ms)觸發

  4. doubleTap

    touchend 中,有上一次的點擊記錄 & 點擊時間差小於 250 ms & 兩次點擊間沒有移動(移動橫縱距離小於 30 px)

  5. longTap

    touchstart 中,添加 750 ms 計時器,在這個時間段內沒有鬆手(touchEnd)移動(touchMove),則觸發

  6. singleTap

    touchend 中,單擊狀況下 250 ms 內沒有再次點擊

  7. rotate

    touchmove 中,觸點多於 1 個,並存在上一次的多點移動記錄時觸發

  8. pinch

    touchmove 中,觸點多於 1 個 & 存在上一次的移動記錄 & 有縮放長度記錄時觸發

  9. pressMove

    touchmove 中,觸點等於 1 個

  10. twoFingerPressMove

    touchmove 中,觸點多於 1 個

  11. swipe

    touchend 中,觸點有移動(移動橫縱距離大於 30 px)

生命週期

重點

  1. 代碼中多處使用 setTimeout(function () {}, 0);, 一方面實現同步轉異步,釋放線程,另外一方面也能確保屏幕滾動時阻止事件的觸發
  2. 滑動時,以最大的移動方向決定水平和豎直方向

    _swipeDirection: function (x1, x2, y1, y2) {
                return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
            }

在閱讀源碼過程當中,對關鍵代碼作了註釋,點我

相關文章
相關標籤/搜索