移动端点击穿透的5种解决方案

移动端点击穿透问题由来

这要追溯至 2007 年初。苹果公司在发布首款 iPhone 前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点的问题。这当中最出名的,当属双击缩放(double tap to zoom),这也是会有上述 300 毫秒延迟的主要原因。双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢? 假定这么一个场景。用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。之前人们刚刚接触移动端的页面,在欣喜的时候往往不会care这个300ms的延时问题,可是如今touch端界面如雨后春笋,用户对体验的要求也更高,这300ms带来的卡顿慢慢变得让人难以接受

那神马是移动端穿透呢?假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,B在300ms后产生的click事件由于找不到B,B会把click事件强行加给A执行,这个过程就叫点击穿透,动画如下

注意!是B先消失后A触发click事件

分析A产生click事件的原因,由于点击B后B会依次发生touchstart--->touchend-->click事件,但当B的touchstart事件产生后,B消失了,B会把它的300ms后产生的click事件强加到它z轴下方的A上,代码如下:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

 <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title>

</head>

<body>

    <style>

    #A{

        font-size:50px;

        width:400px;

        height:400px;

        background:gray

    }

    #B{

        font-size:50px;

        width:400px;

        height:400px;

        background:blue;

        position:absolute;

        left: 200px;

        top: 200px;

    }

    </style>

<div id="A">A</div>

<div id="B">B:点我穿透A</div>

    <script>

    let A=document.getElementById('A')

    let B=document.getElementById('B')

    B.addEventListener('touchstart',function(){

        B.style.display="none"

    })

    A.addEventListener('click',function(){

        console.log('A:啊!我被穿透了')

    })

    </script>

</body>

</html>

大家请注意我把meta标签注释了,因为当我们在 meta标签加上 width=device-width 和 user-scalable=0时,移动端的浏览器就会自动去掉click的事件300ms的延时,因为我们已经为用户适配了页面大小和阻止了用户缩放,所有浏览器就不用判断用户双击缩放了,因此浏览器就自动取消了click事件300ms的延迟

那么如何消除点击穿透呢,大家先来看这张图。

300ms延迟 

小编第一次学习解决移动端点击穿透的时候,觉得这之间非常绕,往往搞不清事件的根源,后来用了简单的数学分析,才觉得思路特别清晰,

首先我们先来看产生点击穿透的必要条件:

1.meta标签没有width=device-width和 user-scalable=0

2.B(mask)蒙版在A之上,且在点击后B在300ms之前消失

3.B(mask)绑定的是touchstart事件,A绑定的是click事件

所以解决的方案无非就是不让上述三种情况不发生而已,是不是瞬间脑子就灵光了。

解决方案:

1.meta 标签设置 width=device-width 和 user-scalable=0

2.在整个项目中只用touchstart事件,缺点:a标签的herf跳转仍需要click事件。

3.在整个项目中只用click事件,优点:使用简单,适合使用对用户点击事件响应实时性不高的        应 用, 缺点:点击仍有300ms的延迟,不适合游戏类的应用

4.在点击B后,不让B立刻消失,给B添加一个渐进(fade)消失的动画效果,时间大于300ms        就可以了

5.最后一个是我觉得是最好的解决方案,消除300ms的延迟后,再使用click事件,使用fastclick         (大小 10kB)这个库来实现,只需要多加几kB的大小,还是很划算的

总结:解决点击穿透的方式还是比较多的,具体使用那种方案还是结合实际项目才能决定

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容