1. 程式人生 > >移動頁面點選穿透問題解決方案

移動頁面點選穿透問題解決方案


核心程式碼:
<div class="content">
<div id="underLayer">
  <a href="www.baidu.com">連結</a>
  <input type="text" class="text1" >
  <input type="select" class="select">
  <input type="radio" class="select">
  <input type="checkbox" class="select">
   <button class="btn" id="openPopup">彈出</button>

</div>
<div id="popupLayer">
        <div class="layer-title">彈出層</div>
        <div class="layer-action">
            <button class="btn" id="closePopup">關閉</button>
        </div>
    </div>
</div>

<script type="text/javascript">
      var oPop =document.getElementById('popupLayer');

      var oUn = document.getElementById('underLayer');
      var oOpen = document.getElementById('openPopup');

      oPop.addEventListener('touchend', function(e){
          this.style.display='none';


      });

     oUn.addEventListener('click', 
       function(){
          alert('1');
      } );


</script>


點選彈出層,touch事件首先被觸發,彈出層和遮罩就被隱藏了。touchend後繼續等待300ms發現沒有其他行為了,則繼續觸發click,由於這時彈出層已經消失,所以當前click事件的target就在底層元素上,於是就alert內容。整個事件觸發過程為 touchend ->  click。
而由於click事件的滯後性(300ms),在這300ms內上層元素隱藏或消失了,下層同樣位置的DOM元素觸發了click事件(如果是input框則會觸發focus事件,如果是<a>連結則會進行頁面跳轉,或是 select / radio / checkbox都會被觸發),看起來就像點選的target“穿透”到下層去了。這就是點透現象
2.解決方法:
a、阻止預設事件  e.preventDefault() 給touchend事件加上  e.preventDefault()
oPop.addEventListener('touchend', function(e){
          this.style.display='none';
          e.preventDefault();
      });

b、利用css3屬性 pointer-events
取值auto|none
當取值為auto 時,效果和沒有定義 pointer-events 屬性相同,滑鼠不會穿透當前層。
當取值為none 時,元素不再是滑鼠事件的目標,滑鼠不再監聽當前層而去監聽下面的層中的元素。但是如果它的子元素設定了pointer-events為其它值,比如auto,滑鼠還是會監聽這個子元素的。
詳細程式碼:
oPop.addEventListener('touchend', function(e){
          this.style.display='none';
          oUn.style.pointerEvents='none';

        setTimeout(function(){
            oUn.style.pointerEvents='auto';
        }, 400);

      });

c. 遮擋
由於 click 事件的滯後性,在這段時間內原來點選的元素消失了,於是便“穿透”了。因此我們順著這個思路就想到,可以給元素的消失做一個fade效果,類似jQuery裡的fadeOut,並設定動畫duration大於300ms,這樣當延遲的 click 觸發時,就不會“穿透”到下方的元素了。
同樣的道理,不用延時動畫,我們還可以在觸控位置放一個透明的元素,這樣當上層元素消失而延遲的click來到時,它點選到的是那個透明的元素,也不會“穿透”到底下。在一定的timeout後再將生成的透明元素隱藏。程式碼如下:
oPop.addEventListener('touchend', function(e){

            oBg.style.display ='block';
          this.style.display='none';

      // 解決方法三
      setTimeout(function(){
           oBg.style.display='none'
        }, 400);


      });