點擊穿透事件原因及解決辦法


移動端touch事件穿透原因及解決辦法

2007 年初。蘋果公司在發布首款 iPhone 前夕,遇到一個問題:當時的網站都是為大屏幕設備所設計的。於是蘋果的工程師們做了一些約定,應對 iPhone 這種小屏幕瀏覽桌面端站點的問題。這當中最出名的,當屬雙擊縮放(double tap to zoom),這也是會有上述 300 毫秒延遲的主要原因。雙擊縮放,顧名思義,即用手指在屏幕上快速點擊兩次,iOS 自帶的 Safari 瀏覽器會將網頁縮放至原始比例。 那么這和 300 毫秒延遲有什么聯系呢? 假定這么一個場景。用戶在 iOS Safari 里邊點擊了一個鏈接。由於用戶可以進行雙擊縮放或者雙擊滾動的操作,當用戶一次點擊屏幕之后,瀏覽器並不能立刻判斷用戶是確實要打開這個鏈接,還是想要進行雙擊操作。因此,iOS Safari 就等待 300 毫秒,以判斷用戶是否再次點擊了屏幕。

click是在移動端有300ms的延遲,混用click和touch會導致穿透事件。

1.蒙層穿透

蒙層綁定了touch事件,而被蒙層覆蓋的元素綁定的是click(或者tap,只要這個事件有延遲,都會發生),touch事件觸發后,蒙層消失,300ms后由於“原先遮擋在前面的蒙層消失了”,click事件就落到了 被覆蓋的元素上面

2.跨頁面點擊穿透

前面說的是被覆蓋的元素添加了click事件,如果被覆蓋的元素沒有綁定click,而是一個a鏈接,或者是input輸入框,也會發生穿透(a鏈接默認就有click跳轉事件)

解決辦法一:設置蒙層消失的延遲

tap后延遲350ms再隱藏mask。先把透明度設置為0,解決視覺層面的效果,在設置定時器延遲,讓蒙層元素消失

$('.mask').on('touchstart', function() { console.log('mask-touchstart'); $(this).css('opacity', 0); setTimeout(function() { $('.mask').css('dispaly', 'none'); }, 350); }) 
解決辦法二:pointer-events,讓被覆蓋元素短時間內無法觸發click

有必要介紹一個 CSS3 的屬性 —— pointer-events。

pointer-events:  auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit;

pointer-events 屬性有很多值,有用的主要是 auto 和 none,其他屬性為 SVG 服務。

屬性 含義
auto 默認值,鼠標或觸屏事件不會穿透當前層
none 元素不再是target,監聽的元素變成了下層的元素(如果子元素設置成 auto,點擊子元素會繼續監聽事件)
$('.mask').on('touchstart', function() { console.log('mask-touchstart'); $(this).css('display', 'none'); //讓被覆蓋元素無法響應click $('.box').css('pointer-events', 'none'); //恢復被覆蓋元素 setTimeout(function() { $('.box').css('pointer-events', 'auto'); }, 300); }) 
解決辦法三:使用fastclick庫

使用fastclick庫,從此所有的點擊事件都使用click,沒有300ms的延遲,也沒有穿透問題

//引入fastclick
<script src="js/fastclick.min.js"></script> 

原生js初始化

if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } 

zepto初始化

FastClick.attach(document.body); 

上面的FastClick.attach(document.body);傳遞的是body元素,代表body元素包括它的子元素都效果,如果想要部分dom元素有這個效果,可以換成相應的don元素

//直接使用click綁定 $('.mask').on('click',function(){ console.log('mask-click'); $(this).css('display','none'); })
解決辦法四:
在上層的布局中增加android:clickable="true"的屬性,這樣下層的事件就不會被觸發了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM