移動端touch拖動事件和click事件衝突問題解決

通過一個懸浮球交互功能的案例來闡述問題,以及解決辦法。

實現效果

類似微信里的懸浮窗效果,蘋果手機的懸浮球功能效果

  1. 可以點擊拖動,然後吸附在窗口邊緣

  2. 點擊懸浮球,可以跳轉介面,或者更改懸浮球的形態

準備

  1. 移動端使用 touch事件類型
  • touchstart當用戶在觸摸平面上放置了一個觸點時觸發 (手指放到螢幕上)

  • touchmove當用戶在觸摸平面上移動觸點時觸發 (手指在螢幕上滑動)

  • touchend當一個觸點被用戶從觸摸平面上移除(抬起手指)

  • touchcancel終止觸摸事件

多點觸控

  1. TouchEvent.targetTouches 只讀

一個 TouchList 對象,是包含了如下觸點的 Touch 對象:觸摸起始於當前事件的目標 element 上,並且仍然沒有離開觸摸平面的觸點。

視口處於第四象限,原點在左上角

event.targetTouches.clientX // 觸摸元素橫坐標
event.targetTouches.clientY // 觸摸元素縱坐標
  1. TouchEvent.touches 只讀

一個 TouchList 對象,包含了所有當前接觸觸摸平面的觸點的 Touch 對象,無論它們的起始於哪個 element 上,也無論它們狀態是否發生了變化。

實現

通過設置懸浮球定位樣式,拖動的時候計算坐標,然後動態的修改懸浮球的定位偏移量,結合transtion過渡效果,實現平滑的過渡

程式碼比較簡單,就不貼了。

問題

當給元素添加了touch事件之後,click事件就不會出發了,那麼怎麼模擬點擊效果呢?

分析

在不了解觸摸事件響應機制的時候,你可能會從計算觸摸目標元素的時長或者計算觸摸起始位置來判定點擊行為,但是這兩種方式都不是最佳的,原因有以下幾點:

  1. 計算觸摸時長比較麻煩

  2. 判斷移動距離不嚴謹,有可能拖動了一圈又回到初始位置

  3. 結合計算觸摸時長和觸摸元素起始位置兩種方式,邏輯比較複雜

下面看我是怎麼做的:

首先應該了解觸摸行為的事件響應機制:

  • 如果有拖動行為,事件執行次序為:touchstart-> touchmove-> touchend

  • 沒有拖動行為,事件執行次序為:touchstart-> touchend

從上面的分析來看,我們可以從touchmove 入手,繼續往下看👇

解決

  1. touchmove事件中增加一個是否移動過的標記isMoved: true

  2. touchend事件中判斷isMoved是否為true,是true則按原有邏輯執行,是false則說明沒有移動過,屬於點擊行為

  3. touchend事件最後,重置isMoved為初始值false,這樣每一個觸摸操作都可以進入同樣的邏輯,不用擔心狀態混亂

完美解決模擬點擊行為🎉🎉


我是 甜點cc

熱愛前端,也喜歡專研各種跟本職工作關係不大的技術,技術、產品興趣廣泛且濃厚,等待著一個創業機會。本號主要致力於分享個人經驗總結,希望可以給一小部分人一些微小幫助。

希望能和大家一起努力營造一個良好的學習氛圍,為了個人和家庭、為了中國的互聯網物聯網技術、數字化轉型、數字經濟發展做一點點貢獻。數風流人物還看中國、看今朝、看你我。

Tags: