登錄 / 注冊

H5案例分享:Touch穿透

0評論 2017-06-19 10:38:28

收藏 | 點贊

 

一、前言

   相信很多移動開發者都有這樣一個體會,那就是我們在移動端點擊事件click對比touchend會有延遲,這是為什么呢?

   其實這是因為覽器在click后會等待約300ms去判斷用戶是否有雙擊行為,手機需要知道用戶是不是想雙擊放大網頁內容。如果300ms內沒有再一次click,那么就判定這是一次單擊行為,所以我們基本上都用(touchstart/touchend),但是這些事件在執行完之后還會執行一次click事件。(至于具體的原因這要從JS事件監聽機制的根本的講起,解釋起來太麻煩,感興趣的同學可以動手了解一下,我們這里就不做過多說明了)。

 

二、touch事件的來源

   PC網頁上的大部分操作都是用鼠標的,即響應的是鼠標事件,包括mousedown、mouseup、mousemove和click事件。一次點擊行為,事件的觸發過程為:mousedown -> mouseup -> click 三步。

   因為手機上沒有鼠標,所以就用觸摸事件touch去實現類似的功能。touch事件包含touchstart、touchmove、touchend,注意手機上并沒有tap事件。手指觸發觸摸事件的過程為:touchstart -> touchmove -> touchend。

   手機上沒有鼠標,但不代表手機不能響應mouse事件,其實是借助touch去觸發mouse事件。有人在PC和手機上對事件做了對比實驗,以說明手機對touch事件相應速度快于mouse事件。

QQ截圖20170619105124.jpg

   從上面的圖表對比中我們可以看出在手機上,當我們手觸碰屏幕時,要過300ms左右才會觸發mousedown事件,所以click事件在手機上看起來就像慢半拍一樣。

 

三、點擊穿透的場景

   點擊穿透的現象主要分為四種:

 

   1.點擊蒙層(Mask Layer)上的關閉按鈕,蒙層消失后發現觸發了按鈕下面元素的click事件。
   蒙層的關閉按鈕綁定的是touch事件,而按鈕下面元素綁定的是click事件,touch事件觸發之后,蒙層消失了,300ms后這個點的click事件出發,事件的目標元素自然就變成了按鈕下面的元素,因為按鈕跟蒙層一起消失了。

 

   2.如果按鈕下面恰好是一個有href屬性的a標簽,那么頁面就會發生跳轉,因為a標簽跳轉默認是click事件觸發,所以穿透原理和上面的完全相同。

 

   3.如果按鈕下面恰好是文本框input或文本域textarea,則文本框或文本域就會獲取焦點,穿透原理和上面的相同。

   4.這次沒有蒙層,直接點擊頁內按鈕跳轉至新頁,然后發現新頁面中對應位置元素的click事件被觸發了。


   和蒙層的道理一樣,js控制頁面跳轉的邏輯如果是綁定在touch事件上的,而且新頁面中對應位置的元素綁定的是click事件,而且頁面在300ms內完成了跳轉,三個條件同時滿足,就出現這種情況了。

   其他的點擊穿透的例子還有很多,我就不一一細說了。

 

四、Touch穿透的解決辦法

   1.延遲

   蒙層被點擊后延時至少300ms再在徹底隱藏掉蒙層顯示下層的內容,缺點是隱藏蒙層變慢了,350ms還是能感覺到慢的,但是這種方法只需要針對蒙層做處理就行了,改動非常小,如果要求不高的話,用這個比較省時省力。

 

   2.增加中間蒙層

   我們還可以動態地在觸摸位置生成一個透明的元素,這樣當上層元素消失而延遲的click來到時,它點擊到的是那個透明的元素,就不會“穿透”到下面去了,然后再在一定的延遲后將生成的透明元素移除。

 

   3.利用pointer-events方法

   pointer-events是CSS3中的屬性,它有很多取值,auto | none | visiblepainted | visiblefill | visiblestroke | visible | painted | fill | stroke | all,有用的主要是auto和none,其他屬性值為SVG服務。

   當pointer-events取值為auto時,效果與pointer-events屬性未指定時的表現效果相同;當取值為none時,元素永遠不會成為鼠標事件的目標,但是,當其后代元素的pointer-events屬性指定其他值時,鼠標事件可以指向后代元素,在這種情況下,鼠標事件將在捕獲或冒泡階段觸發父元素的事件偵聽器。

$('.button').on('touchstart',function(){
  $('.upbox').hide();
  $('.underbox').hide();
  //馬上讓它不能點擊
  $('.underbox').css('pointer-events','none');
  //因為click事件需要300ms響應,所以我們時間定義360ms,時間一過又可以正常點擊了
  setTimeout(function(){$('.underbox').css('pointer-events','auto')},360);
});

   

   4.只用click

   頁面里的點擊事件都用click來觸發,但是這樣的話,頁面里的點擊交互都將增加300ms延遲,想想都慢,但是如果交互性要求不高的話可以這么做,強烈不推薦 ,快一點總是好的。

 

   5.使用fastclick插件

   如果不介意多加載幾KB的話,可以使用fastclick庫,其實現思路是:取消 click 事件,用 touchend 模擬快速點擊行為,從此所有點擊事件都使用click,不會出現“穿透”的問題,并且沒有300ms的延遲。不建議使用,因為有人遇到了bug, fastclick 導致click事件觸發兩次的問題,而且開發者還必須先引入fastclick庫,再把頁面內所有touch事件都換成click,稍微有點麻煩,而且多引入幾KB的文件只是為了解決點透問題不值當,不如用前三種方法中的任一種。

 

五、總結

   除了上面這五種辦法外,相信還有其他我本文中未收錄的方法,這就需要大家一起來探索了,其實遇到問題,第一重要的不是立即著手解決問題,而是找到問題的根源所在,之后針對根源去消滅問題,至于解決問題的方法,一千個人眼中一千個哈姆雷特,你喜歡哪種,就用那種方法來。

 

文章來源:“H5案例分享”團隊原創文章

0 條評論

分享
公眾號
公眾號二維碼

? 2017 志進科技 版權所有 上海志進信息科技有限公司 備案號滬ICP備14017051號-2

欧美性生活大片免费看,中文字幕在线亚洲日韩制服在线,国产高清精品福利私拍国产写真,免费AV片在线观看网址,西西大胆午夜视频无码,性AA片在线观看