移動端手勢封裝

一、手勢封裝的兼容與實驗
在微信瀏覽器及手機自帶瀏覽器當中的自帶手勢會影響事件的觸發
微信的自帶手勢包括但不僅限於

  • 頁面頂部下拉刷新
  • 長按彈出菜單
  • 上下滑動翻動頁面
  • 雙指縮放

在有默認手勢時可能出現的問題有無法正常觸發touchend事件,使用小米、vivo、oppo、蘋果進行實驗,實驗結果如下:
1、下滑手勢中小米和oppo不觸發touchend事件觸發下拉刷新,蘋果和vivo均觸發touchend,但vivo不觸發下拉刷新。
2、上滑、左滑、右滑手勢中均正常觸發touchend事件
3、長按時oppo和小米不觸發touchend並彈出系統菜單,vivo不觸發touchend且不彈出系統菜單,蘋果觸發touchend且不彈出系統菜單但默認選中最後一行文字並彈出複製菜單
4、縮小時四款機型均正常觸發touchend,,蘋果有縮小再彈開的動畫,其他機型無
5、放大和放大後再縮小四款機型均可以獲取到touchend且縮放效果正常
6、旋轉時touchend觸發正常,蘋果有縮小再彈開的動畫,其他機型無
7、以單擊形式觸屏時四款手機均以touchstart、touchend、mousedown、mouseup的順序觸發事件。再加入mousemove監聽後小米、vivo、oppo以touchstart、touchend、mousemove、mousedown、mouseup的順序觸發事件。蘋果觸發touchstart、touchend、mousemove順序觸發事件且不再觸發mousedown和mouseup
8、長按時觸發touchcancel的timeStamp與該觸點的touchstart的timeStamp相同,下滑觸發cancel時timeStamp爲實際值

此時的解決方式有兩種,一是禁止默認事件,但是這樣影響比較大,而是使用touchcancel使得在瀏覽器觸發默認事件後仍可以監聽自己封裝的手勢

1、禁止瀏覽器默認事件
默認情況下,平移(滾動)和縮放手勢由瀏覽器專門處理。 使用 Pointer_events 的應用程序將在瀏覽器開始處理觸摸手勢時收到一個 pointercancel 事件。 通過明確指定瀏覽器應該處理哪些手勢,應用程序可以在 pointermove 和 pointerup 監聽器中爲其餘的手勢提供自己的行爲。 使用 Touch_events 的應用程序通過調用 preventDefault() 禁用瀏覽器處理手勢,但也應使用觸摸操作確保瀏覽器在調用任何事件偵聽器之前,瞭解應用程序的意圖。

當手勢開始時,瀏覽器與觸摸的元素及其所有祖先的觸摸動作值相交直到一個實現手勢(換句話說,第一個包含滾動元素)的觸摸動作值。 這意味着在實踐中,觸摸動作通常僅適用於具有某些自定義行爲的單個元素,而無需在該元素的任何後代上明確指定觸摸動作。 手勢開始之後,觸摸動作值的更改將不會對當前手勢的行爲產生任何影響。

  • css方面的默認事件禁用
// 禁止用戶選擇複製
user-select: none;
// 指定某個給定的區域是否允許用戶操作
touch-action: none;
  • js方面的禁用

    在需要禁用事件上使用preventDefault()來禁止默認事件

  target.addEventListener('touchstart', e => {
     e.preventDefault()
  })

2、使用touchcancel的方式結局兼容性問題
先來看看w3c中關於touchcancel的描述

用戶代理必須發送此事件類型, 以指示觸點在特定於實現的方式中中斷時, 例如來自 UA 取消觸摸的同步事件或操作, 或將文檔窗口保留到可以處理用戶交互的非文檔區域。(例如, UA 的本地用戶界面、插件)當用戶在觸摸面上放置更多觸摸點時, 用戶代理也可以發送此事件類型, 而不是將設備或實現配置爲存儲, 在這種情況下, TouchList中最早的觸摸對象應刪除。
該事件的目標必須是與第一次放置在接觸面上的觸摸點相同的元素,即使觸摸點已經移動到目標元素的交互區域之外。
任何被移除的觸點都應當包含在TouchEvent的changedTouches屬性當中。且不應當包含在touches屬性和targetTouches屬性當中。

因此如果瀏覽器默認事件使得touchend事件沒有觸發則會發送touchcancel用來表示原油touch事件的監聽實現中段。然後將可能會監聽不到的touchend的處理放入touchcancel當中就可以判定用戶操作了

再解決完以上問題後就可以再各種情況下都能夠監聽到用戶的手勢了,具體封裝代碼請點擊 手勢封裝方法

二、TouchEvent
1、touchEvent規範(譯自W3C的TouchEvent部分)
Touches接口
此接口描述觸摸事件的單個觸點。觸摸對象是不可變的;創建一個後,其屬性不能更改。

只讀屬性長標識符
每個觸點的標識號。當觸點變爲活動狀態時, 必須爲其分配一個與任何其他活動觸點不同的標識符。當觸點保持活動狀態時, 引用它的所有事件都必須爲其分配相同的標識符.

只讀屬性 EventTarget 目標
當觸點在第一次放置在表面上時開始的 EventTarget, 即使在該元素的交互式區域之外,觸頭也已移動。

只讀屬性雙 screenX
相對於屏幕的點的水平座標 (以像素爲單位)

只讀屬性雙 screenY
點相對於屏幕的垂直座標 (以像素爲單位)

只讀屬性雙 clientX
點相對於視區的水平座標 (以像素爲單位), 不包括任何滾動偏移量

只讀屬性雙 clientY
點相對於視區的垂直座標 (以像素爲單位), 不包括任何滾動偏移量

只讀屬性雙 pageX
點相對於視區的水平座標 (以像素爲單位), 包括任何滾動偏移量

只讀屬性雙 pageY
點相對於視區的垂直座標 (以像素爲單位), 包括任何滾動偏移量

TouchList接口
此接口定義touchstart、touchend、touchmove、touchcancel事件類型。TouchEvent對象是不可變的;創建並初始化一個後,其屬性不能更改。

只讀屬性touches
接觸面上每一個觸點的Touches對象信息列表

只讀屬性targetTouches
接觸面上每一個開始於目標元素的觸點的Touches對象信息列表

只讀屬性changedTouches
與本事件觸發相關的觸點的Touches對象信息列表
對於touchstart事件, 這必須是剛剛成爲當前事件激活狀態的觸點列表。對於touchmove事件, 這必須是自上次事件以來移動的觸摸點列表。對於touchend和touchcancel事件, 這必須是剛剛從曲面中移除的觸摸點的列表。

touchEvent事件
1、touchstart事件
用戶代理必須發送此事件類型,以芝士用戶何時在觸摸屏上放置觸摸點。
此事件的目標必須是元素,如果觸點謂語框架內,則應將該事件分派到子瀏覽上下文的框架
如果在此事件上調用preventDefault方法則它應該防止與同一個活動觸摸點關聯的任何觸摸事件導致的任何默認操作,包括鼠標事件或滾動

2、touchend事件
用戶代理必須發送此事件類型,以指示用戶合適從觸摸屏上刪除觸點,也包括點物理離開觸屏的情況,如被拖離屏幕。
該事件的目標必須是與第一次放置在接觸面上的觸摸點相同的元素,即使觸摸點已經移動到目標元素的交互區域之外。
任何被移除的觸點都應當包含在TouchEvent的changedTouches屬性當中。且不應當包含在touches屬性和targetTouches屬性當中。
如果此事件被取消,則任何包含此事件的事件序列都不應該作爲click被解釋。

3、touchmove事件
用戶代理必須發送此事件類型,以只是用戶合適沿觸摸屏移動觸摸點。
該事件的目標必須是與第一次放置在接觸面上的觸摸點相同的元素,即使觸摸點已經移動到目標元素的交互區域之外。
注意,用戶代理髮送觸摸移動事件的速率是由實現定義的,並且可能取決於硬件能力和其他實現細節。
用戶代理應當阻止由於任何touchmove事件觸發的默認行爲直到至少一個與相同活動觸點關聯的touchmove事件不被取消爲止。在至少一個與相同活動觸點相關聯的touchmove事件沒有被取消之後,touchmove事件的的默認事件是否被取消取決於實現。

4、touchcancel事件
用戶代理必須發送此事件類型, 以指示觸點在特定於實現的方式中中斷時, 例如來自 UA 取消觸摸的同步事件或操作, 或將文檔窗口保留到可以處理用戶交互的非文檔區域。(例如, UA 的本地用戶界面、插件)當用戶在觸摸面上放置更多觸摸點時, 用戶代理也可以發送此事件類型, 而不是將設備或實現配置爲存儲, 在這種情況下, TouchList中最早的觸摸對象應刪除。
該事件的目標必須是與第一次放置在接觸面上的觸摸點相同的元素,即使觸摸點已經移動到目標元素的交互區域之外。
任何被移除的觸點都應當包含在TouchEvent的changedTouches屬性當中。且不應當包含在touches屬性和targetTouches屬性當中。

5、與鼠標事件的交互
用戶代理可能會在用戶操作想用的時候同時調度touch事件和mouse事件。如果用戶代理在單一的用戶操作中同時調度touch事件和mouse事件,那麼touchstart應當在任何鼠標事件調度之前被調度。如果調用了touchstart、touchmove或touchend的prevebtDefault方法,那麼用戶代理不應當調度任何作爲被阻止作爲touch事件結果的mouse事件
如果用戶代理以單擊方式觸發一系列touch事件,那麼它應當在觸摸事件相應的位置觸發mousemove, mousedown, mouseup, 和click 事件(以此順序)。如果在觸摸事件期間文檔內容發生改變,則用戶代理可以將鼠標事件分派到與touch事件不同的目標。
默認行爲和touch事件和鼠標事件的的序列都由實現定義,除非另有指定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章