移动端H5,Hybird开发点击穿透事件处理

2023-11-30 21:08

本文主要是介绍移动端H5,Hybird开发点击穿透事件处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

What

现象描述: 页面中存在上下两个层,上层元素具有表单,链接或者绑定相应事件,上层元素点击或触摸,导致上层DOM改变,下层中同样位置的 元素触发点击事件。这种现象就是点击穿透(Ghost Clicks)。

要理解这种现象,首先要了解移动端的相关事件 —— 触摸(Touch)事件,点击(Click)事件。以及移动端事件触发的顺序关系:

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

Touch 事件中,常用的为 touchstart, touchmove, touchend 三种。除此之外还有touchcancel。 注意,原生事件中并没有tap事件。下面会解释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 记录触摸结束信息。 通过上述这些参数,很容易的去计算幽冥点击的时间,以及点击穿透的相关信息,包括响应的坐标情况。

Why

问题来了,click 事件什么时候触发?

浏览器在 touchend 之后会等待约 300ms ,如果没有 tap 行为,则触发 click 事件。 而浏览器等待约 300ms 的原因是,判断用户是否是双击(double tap)行为,双击过程中就不适合触发 click 事件了。 由此可以看出 click 事件触发代表一轮触摸事件的结束。

上面说到原生事件中并没有 tap 事件,可以参考经典的 zepto.js 对 singleTap 事件的处理(遗憾的是在部分浏览器中,依然存在点击穿透的问题)。可以看出,singleTap 事件的触发时机 —— 在 touchend 事件响应 250ms 无操作后,触发singleTap。因此,点击穿透的现象就容易理解了,在这 300ms 以内,因为上层元素隐藏或消失了,由于 click 事件的滞后性,同样位置的 DOM 元素触发了 click 事件(如果是 input 则触发了 focus 事件)。在代码中,给我们的感觉就是 target 发生了飘移。

如何处理点击穿透(思路)

1. 触摸开始时 touchstart 事件触发时,preventDefault()。毫无疑问,很容易想到这一点,而且也从根本上解决了这个问题。但是,它有一个避免不了或者说引入了很大的缺陷,页面中DOM 元素无法再进行滚动了。这个方法显然不能满足我们的需求,但是这个思路其实可以给我们更多的启发,比如说 iscroll 只允许横向滚动的实现,相关实现这里暂且不表。

2. 触摸结束时 touchend 事件触发时,preventDefault()。看上去好像没有什么问题,但是,很遗憾的是不是所有的浏览器都支持。

3. 禁止页面缩放 通过设置meta标签,可以禁止页面缩放,部分浏览器不再需要等待 300ms,导致点击穿透。点击事件仍然会触发,但相对较快,所以 click 事件从某种意义上来说可以取代点击事件, 而代价是牺牲少数用户(click 事件触发仍然较慢)的体验。

<meta name="viewport" content="width=device-width, user-scalable=no">

移动端chromiun 和 iOS 9.3+ 可以用 CSS 属性来阻止元素的双击缩放进而取消点击穿透的延迟:

html {-ms-touch-action: manipulation;touch-action: manipulation;
}  

4. CSS3 的方法 虽然主要讲的是事件,但是有必要介绍一个 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,点击子元素会继续监听事件)

5. 处理点击事件 —— Touch to Click 最靠谱的方案还是从点击事件的根源上解决问题。用 js 去判断幽冥点击,然后阻止点击穿透。这种方式显然可以实现,缺点是阻止点击穿透时需要小心,不要导致原生的 HTML 元素(如:链接,多选框,单选框)无法正常运行。

通过上文中介绍的 touches,targetTouches,changedTouches 参数,我们可以构建出这样的测试页面,可以统计出点击穿透的时间,以及已经响应的情况。

 preventDefault()点击穿透时间点击穿透区域
 touchstarttouchend缩放页面禁止缩放页面缩放页面禁止缩放页面
Safari Mobile iOS 5.1.1YesYes370ms after end370msafter endtouchstarttouchstart
Safari Mobile iOS 6.1.3YesYes370ms after end370msafter endtouchstarttouchstart
Safari Mobile iOS 7.1.1YesYes370ms after end370msafter endtouchstarttouchstart
Android 2.3.7YesNo410ms after end410msafter endtouchstarttouchstart
Android 4.0.4YesNo300ms after end10ms after endtouchstarttouchstart
Android 4.1.2YesNo300ms after end300msafter endtouchstarttouchstart
Android 4.2.2YesNo300ms after start10ms after endtouchstarttouchend
IE10 Windows Phone 8NoNo310ms after end10ms after endtouchendtouchend
Blackberry 10YesYes260ms after end10ms after endtouchstarttouchstart
Chrome for iOSYesYes360ms after end360msafter endtouchstarttouchstart
Chrome for AndroidYesYes300ms after start10ms after endtouchstarttouchend
Firefox for AndroidYesNo300ms after end10ms after endtouchstarttouchend

由此可以看出: 1. 点击穿透受浏览器和页面是否缩放影响 2. 点击穿透有两种情况:快速情况有 10ms 慢速情况有 300ms 3. 在 touchend 时间上调用 preventDefault() 可以阻止多数情况的点击穿透

代码上处理建议如下:

  1. 在touchend事件上调用 preventDefault()
  2. 在一次成功的点击后,建议接下来的 500ms 以内取消所有的 click 事件。
  3. 分析点击事件,判断如果是慢速点击穿透,则取消所有 click 事件,如果是快速点击穿透,取消触摸事件 50ms以内的 click 事件即可。

别的参考思路(开源库fastclick),取消 click 事件,用touchend 模拟 快速点击行为。

参考文章

  1. Ghost clicks in mobile browsers
  2. 300ms tap delay gone away
  3. Javascript Powered Webapps and Click Versus Tap
  4. Fast Buttons

这篇关于移动端H5,Hybird开发点击穿透事件处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/438556

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

JavaScript DOM操作与事件处理方法

《JavaScriptDOM操作与事件处理方法》本文通过一系列代码片段,详细介绍了如何使用JavaScript进行DOM操作、事件处理、属性操作、内容操作、尺寸和位置获取,以及实现简单的动画效果,涵... 目录前言1. 类名操作代码片段代码解析2. 属性操作代码片段代码解析3. 内容操作代码片段代码解析4.

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE