一、前言

移动端浏览器提供一个特殊的功能:双击(double tap)缩放。

 

二、移动端延迟300ms的原因

为什么要用触摸事件?触摸事件是移动端浏览器特有的html5事件。

因为移动端的click有很大延迟(大约300ms),300ms延迟来自判断双击和长按,因为只有默认等待时间结束以确定没有后续动作发生时,才会触发click事件。而触摸事件的延迟则是非常短的,使用触摸事件的能够提高页面响应速度,带来更好的用户体验。

重点:由于移动端会有双击缩放的这个操作,因此浏览器在click之后要等待300ms,看用户有没有下一次点击,也就是这次操作是不是双击。

三、浏览器开发商的解决方案

1、方案一:禁用缩放

当HTML文档头部包含如下meta标签时:

<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">

表明这个页面是不可缩放的,那双击缩放的功能就没有意义了,此时浏览器可以禁用默认的双击缩放行为并且去掉300ms的点击延迟

缺点:就是必须通过完全禁用缩放来达到去掉点击延迟的目的,然而完全禁用缩放并不是我们的初衷,我们只是想禁掉默认的双击缩放行为,这样就不用等待300ms来判断当前操作是否是双击。但是通常情况下,我们还是希望页面能通过双指缩放来进行缩放操作,比如放大一张图片,放大一段很小的文字。

2、方案二:更改默认的视口窗口

为了让桌面站点能在移动端浏览器正常显示,移动端浏览器默认的视口宽度!=设备浏览器视窗宽度,而是视口宽度要比设备宽度大,通常是980px。

我们可以通过以下标签来设置视口宽度设备宽度

<meta name="viewport" content="width=device-width">

对移动端坐过适配和优化了,这个时候就不需要双击缩放了。如果能够识别出一个网站是响应式的网站,那么移动端浏览器就可以自动禁掉默认的双击缩放行为并且去掉300ms的点击延迟。如果设置了上述meta标签,那浏览器就可以认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了。

这个方案相比方案一的好处在于,它没有完全禁用缩放,而只是禁用了浏览器默认的双击缩放行为,但用户仍然可以通过双指缩放操作来缩放页面

方案三:css 的 touch-action

除了IE之外的大部分浏览器都不支持这个新的CSS属性。touch-action这个CSS属性。这个属性指定了相应元素上能够触发的用户代理(也就是浏览器)的默认行为。如果将该属性值设置为touch-action: none,那么表示在该元素上的操作不会触发用户代理的任何默认行为,就无需进行300ms的延迟判断

四、代码解决方案

1、方案一:指针事件polyfill

除了IE,其他大部分浏览器都还不支持指针事件。有一些JS库,可以让我们提前使用指针事件。比如:

(1)谷歌的Polymer

(2)微软的HandJS

(3)@Rich-Harris 的 Points

关心的不是指针事件,而是与300ms延迟相关的CSS属性touch-action。由于除了IE之外的大部分浏览器都不支持这个新的CSS属性,所以这些指针事件的polyfill必须通过某种方式去模拟支持这个属性。一种方案是JS去请求解析所有的样式表,另一种方案是将touch-action作为html标签的属性。

 

2、方案二:FastClick

FastClick是FT Labs专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉。

五、点击穿透问题

说完移动端点击300ms延迟的问题,还不得不提一下移动端点击穿透的问题。既然click点击有300ms的延迟,那对于触摸屏,我们直接监听touchstart事件不就好了吗?

使用touchstart去代替click事件有两个不好的地方。

第一:touchstart是手指触摸屏幕就触发,有时候用户只是想滑动屏幕,却触发了touchstart事件,这不是我们想要的结果;

第二:使用touchstart事件在某些场景下可能会出现点击穿透的现象。

1、什么是点击穿透?

假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。

这是因为在移动端浏览器事件执行的顺序是touchstart > touchend > click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。

2、点击穿透现象3种情况

(1)点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件。

(2)跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同

(3)点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了。

3、解决方案

2种思路:

(1)不要混用touch和click。既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了。

(2)用掉(或者说是消费掉)touch之后的click。依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)

详细方案:

(1)只用touch

最简单的解决方案,完美解决点击穿透问题。

把页面内所有click全部换成touch事件 touchstart 、’touchend’、’tap’, 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。

(2)只用click

下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢。不用touch就不会存在touch之后300ms触发click的问题。

(3)拿个东西挡住

比较笨的方法, 千万不要用。更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

(4)tap后延迟350ms再隐藏mask

改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的。

(5)pointer-events

比较麻烦且有缺陷, 不建议使用。mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应。缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现。

(6)在下面元素的事件处理器里做检测(配合全局flag)

比较麻烦, 不建议使用。全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应。

(7)fastclick

好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题。

首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢。

六、浏览器事件触发的顺序

touchstart --> mouseover(有的浏览器没有实现) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend

Touch 事件中,常用的为 touchstart, touchmove, touchend 三种。除此之外还有touchcancel。 注意,原生事件中并没有tap事件。

事件描述如下:

事件 描述 触发时机
touchstart 开始触摸 手指接触屏幕时立即触发
touchmove 移动或拖拽 取决于系统和浏览器
touchend 触摸结束 手指离开屏幕时立即出发

而Touch事件的触发一般通过手指,还会存在多点触控,拖拽方向等情况。列出几个重要参数如下:

参数 含义
touches 屏幕中每根手指信息列表
targetTouches 和touches类似,把同一节点的手指信息过滤掉
changedTouches 响应当前事件的每根手指的信息列表

代码获取如下:

elemenrRef.addEventListener('touchstart', function(e) {   console.log(e.touches, e.targetTouches, e.changedTouches);} );

手指触发触摸事件的过程如下:

touchstart --> mouseover(有的浏览器没有实现) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend

由此,我们可以在 ontouchstart 事件上记录开始触摸开始,ontouchend 记录触摸结束信息。 通过上述这些参数,很容易的去计算幽冥点击的时间,以及点击穿透的相关信息,包括响应的坐标情况

【注:我是saucxs,也叫songEagle,松宝写代码,文章首发于sau交流学习社区 https://www.mwcxs.top),关注我们每天精彩内容】

转载于:https://www.cnblogs.com/chengxs/p/11064469.html

设计方案--移动端延迟300ms的原因以及解决方案相关推荐

  1. 苹果浏览器移动端click事件延迟300ms的原因以及解决办法

    这要追溯至 2007 年初.苹果公司在发布首款 iPhone 前夕,遇到一个问题 -- 当时的网站都是为大屏幕设备所设计的.于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点 ...

  2. 网络直播中延迟产生的原因及解决方案

    背景 rtsp转rtmp推流器是我们公司的一款独家产品,主要用途是将普通视频监控的rtsp视频流转为rtmp流推送到各大直播平台,支持几乎市面上所有的IPC摄像头.在实际使用过程中,不同的客户对直播延 ...

  3. fastclick 解决移动端click事件延迟300ms和点击穿透问题

    一.移动端click点击事件300ms延迟介绍 在正常情况下,如果不进行特殊处理,移动端在触发点击事件时,会有300ms的延迟.换句话说,当我们在点击移动端页面后不会立即做出反应,而是会等待300ms ...

  4. 移动端点击延迟300ms传说 你听过吗

    「 H5开发引发问题 」 上篇文章刚说了 不要把公司当成家,然后这周我就差点把公司当家了,每天回去很晚,总之加班了. 然后在做项目的过程中,发现了一个由来已久的传说, 300ms延迟问题,可能很多同学 ...

  5. 基于http-flv的抖音直播端到端延迟优化实践

    延迟是怎么产生的? 传统直播方案(http-flv.RTMP 等)的架构以及延迟量级如下图所示: 以抖音直播为例,直播链路各环节延迟贡献如下: 推流端--网络延迟平均 20 - 30ms,编码延迟依赖 ...

  6. MySQL主从同步延迟原因与解决方案

    一.MySQL数据库主从同步延迟产生的原因 MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高.Slave的SQL Thr ...

  7. MySQL出现同步延迟有哪些原因?如何解决?

    MySQL出现同步延迟有哪些原因?如何解决?   1.从库太多导致复制延迟 优化:建议从库数量3-5个为宜   2.从库硬件比主库硬件差 优化:提升硬件性能   3.慢SQL语句过多 优化:SQL语句 ...

  8. click事件延迟300ms,处理方法-----FastClick

    下载地址:https://github.com/ftlabs/fastclick http://amazeui.org/1.x/javascript/fastclick/ 从点击屏幕上的元素到触发元素 ...

  9. 球球大作战显示中国服务器较差,球球大作战延迟卡顿原因分析及解决方法

    球球大作战想必不用说也知道多火了吧,小编周围的朋友都在玩,当然在玩的时候要是卡顿延迟的话就会让游戏体验大打折扣了,那么出现延迟卡顿要怎么解决呢?下面就让小编来告诉你处理的方法. 球球大作战延迟卡顿 球 ...

最新文章

  1. 用execSQL语句建表时提示“syntax error”原因及解决方法
  2. 酒店用机器学习,预测哪些客人会放鸽子
  3. requests + BeautifulSoup + json
  4. March 2007 CTP Linq 的一些改变
  5. MySQL——MySQL的数据查询功能
  6. java 中对对象的调用
  7. 如何在浏览器里开发并运行 SAP UI5 应用
  8. 久玩玉之魂服务器维护,玉之魂1级到57级挂机心得详情分享
  9. LeetCode 127. 单词接龙(广度优先遍历)
  10. 内联失败函数变成static函数的一些问题
  11. WebRTC sdp详解
  12. java定义类和测试类时的三种方式
  13. 倍福嵌入式控制器PLC各型号介绍
  14. 前端模块化发展(CommonJs、AMD、CMD、UMD、ESM)
  15. 红米note3android5.0,小米红米note3MOSBeta5.0安卓8.1.0来去电归属农历等本地化增强适配...
  16. Python 反编译:pycdc工具的使用
  17. Linux命令简写与全称
  18. 放大器指标:1db压缩点
  19. BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议)
  20. 使用360浏览器出现域名解析错误和有道词典连接不了网络的解决方法

热门文章

  1. 如何画正太分布曲线_python scipy.stats实现各种常见的统计分布
  2. c java交互,Java与C交互
  3. 记忆化搜索本质是dp
  4. 通过触发绑定切换下拉框的数据
  5. JQueryDOM之样式操作
  6. python列表内元素求和_Python之list对应元素求和
  7. Go语言基础进阶—程序结构—类型
  8. [leetcode]376. 摆动序列
  9. oracle当前用户创建的表不可见?
  10. bzoj 1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(暴力)