zoukankan      html  css  js  c++  java
  • 点击穿透事件原因及解决办法

    移动端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"的属性,这样下层的事件就不会被触发了。
  • 相关阅读:
    MySQL 5.6中如何定位DDL被阻塞的问题
    MySQL 5.7中如何定位DDL被阻塞的问题
    MySQL表结构变更,不可不知的Metadata Lock
    mysqlfrm
    升级MySQL5.7,开发不得不注意的坑
    MySQL root密码忘记,原来还有更优雅的解法!
    MySQL 8 新特性之自增主键的持久化
    ip route显示和设定路由
    RHEL7/CentOS7 ip 命令常用用法,代替 ifconfg/route/ifup/ifdown
    网络安全+运维进阶(79)-网络基础-网络基础
  • 原文地址:https://www.cnblogs.com/leftJS/p/11095226.html
Copyright © 2011-2022 走看看