yanyue404/blog

移动端的300毫秒点击延迟和点击穿透问题

Opened this issue · 0 comments

300毫秒延迟来历

在早期iphone设备中为了更好的适应设备网页的比例,加入双击缩放会将浏览器的网页缩放至原始比例。

当浏览器单击一次屏幕,浏览器需要去判断用户是想要打开链接还是会选择双击缩放,这就导致需要等待300毫秒来做进一步的判断。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕.

在现今的移动web中,300毫秒的延迟影响了用户体验,大家都在想办法优化这个体验,300 毫秒点击延迟的来龙去脉阐述的更加清楚明白。

解决方法之Hammer.js

hammer.js是一款开源的移动端脚本框架,他可以完美的实现在移端开发的大多数事件,如:点击、滑动、拖动、多点触控等事件。不需要依赖任何其他的框架,并且整个框架非常小,在使用时非常简单,代码示例如下:

hammer中的tap事件

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width" />
    <title>Tap</title>
    <script src="./js/hammer.js"></script>
    <style type="text/css">
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0px;
            padding: 0px;
        }

        .test {
            width: 100%;
            height: 50%;
            background: #ffd800;
            text-align: left;
        }

        .result {
            width: 100%;
            height: 50%;
            background: #b6ff00;
            text-align: left;
        }
    </style>
</head>

<body>
    <div id="test" class="test">事件区域</div>
    <div id="result" class="result">事件结果:点击触发
        <br />
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        //创建一个新的hammer对象并且在初始化时指定要处理的dom元素
        var hammertime = new Hammer(document.getElementById("test"));
        //添加事件
        hammertime.on("tap", function (e) {
            document.getElementById("result").innerHTML += "tap点击触发了,长按无效" + new Date().getTime() + "<br />";
            //控制台输出
            console.log(e);
        });


        document.querySelector("#test").onclick = function () {
            document.getElementById("result").innerHTML += "原生点击触发了,长按无效" + new Date().getTime() + "<br />";
        }

        $("#test").click(function () {
            $("#result")[0].innerHTML += "jq点击触发了,长按无效" + new Date().getTime() + "<br />";
        })
    </script>
</body>

</html>
})

设备测试

chrome和qq都不明显看不出来,safari...

chrome

image

qq

image

自己写一个tap方法

在这里利用是否支持touch事件来做分别,支持的话使用touch事件,不支持则使用mouse事件,最后触发时间范围小于500毫秒的回调函数,也是可以使用的!

function tap(ele, touchFn) {

  var SupportsTouches = ("createTouch" in document), //判断是否支持触摸
    StartEvent = SupportsTouches ? "touchstart" : "mousedown", //支持触摸式使用相应的事件替代
    EndEvent = SupportsTouches ? "touchend" : "mouseup";

  var startTime = null,
    endTime = null;
  ele.addEventListener(StartEvent, function (e) {

    startTime = e.timeStamp
    console.log("startTime " + new Date().getTime())

  })
  ele.addEventListener(EndEvent, function (e) {
    var context = this;

    endTime = e.timeStamp
    console.log("endTime " + new Date().getTime())
    console.log('间距=' + (endTime - startTime))
    if (endTime - startTime < 500) {
      touchFn();
    }

  })
}

tap(document.querySelector("div"), function () {
  console.log("complate " + new Date().getTime())
})

浏览器打印

image

Userful links