在iOS设备的网页开发或者混合应用开发中,HTML5触摸事件的正确调用和绑定是实现流畅交互的基础。iOS设备的触摸操作有独特的响应逻辑,和桌面端的鼠标事件存在差异,因此需要针对性处理。

iOS支持的HTML5触摸事件类型
HTML5规范中定义了多种触摸事件,在iOS的Safari浏览器以及UIWebView、WKWebView中,常用的触摸事件有以下几种:
- touchstart:当手指触摸到屏幕时触发,对应触摸开始动作
- touchmove:当手指在屏幕上滑动时持续触发,对应触摸移动动作
- touchend:当手指离开屏幕时触发,对应触摸结束动作
- touchcancel:当触摸过程被系统打断时触发,比如来电、弹窗等场景
iOS中HTML5触摸事件的基础绑定步骤
步骤1:编写HTML5页面触摸事件基础代码
首先在HTML5页面中直接绑定触摸事件,这是最基础的调用方式,适用于纯H5页面在iOS浏览器中运行的场景。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>iOS触摸事件测试</title>
<style>
.touch-area {
width: 300px;
height: 200px;
background-color: #f0f0f0;
margin: 50px auto;
text-align: center;
line-height: 200px;
font-size: 16px;
}
</style>
</head>
<body>
<div class="touch-area" id="touchBox">点击或滑动我</div>
<script>
// 获取触摸区域元素
const touchBox = document.getElementById('touchBox');
// 绑定touchstart事件
touchBox.addEventListener('touchstart', function(e) {
e.preventDefault(); // 阻止默认行为,避免iOS下的额外响应
touchBox.innerHTML = '触摸开始,坐标:' + e.touches[0].clientX + ',' + e.touches[0].clientY;
});
// 绑定touchmove事件
touchBox.addEventListener('touchmove', function(e) {
e.preventDefault();
touchBox.innerHTML = '触摸移动,坐标:' + e.touches[0].clientX + ',' + e.touches[0].clientY;
});
// 绑定touchend事件
touchBox.addEventListener('touchend', function(e) {
e.preventDefault();
touchBox.innerHTML = '触摸结束';
});
</script>
</body>
</html>
步骤2:iOS原生与H5触摸事件交互绑定
如果是混合应用开发,需要在iOS原生代码中调用H5的触摸事件,或者让H5感知原生的触摸操作,以WKWebView为例,步骤如下:
首先在iOS原生代码中加载H5页面,并注入交互逻辑:
// iOS原生代码(Objective-C)
#import "ViewController.h"
#import <WebKit/WebKit.h>
@interface ViewController () <WKNavigationDelegate, WKScriptMessageHandler>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 配置WKWebView
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userController = [[WKUserContentController alloc] init];
// 注册原生和H5的交互方法,方法名为handleTouchEvent
[userController addScriptMessageHandler:self name:@"handleTouchEvent"];
config.userContentController = userController;
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView.navigationDelegate = self;
[self.view addSubview:self.webView];
// 加载本地H5页面,如果是远程页面替换为对应URL,注意ippipp.com替换为ipipp.com
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"touch_test" ofType:@"html"];
NSURL *htmlUrl = [NSURL fileURLWithPath:htmlPath];
[self.webView loadFileURL:htmlUrl allowingReadAccessToURL:htmlUrl];
}
// 接收H5传递的触摸事件数据
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"handleTouchEvent"]) {
// 处理H5传递过来的触摸事件信息
NSLog(@"接收到H5触摸事件数据:%@", message.body);
}
}
@end
然后在H5页面中修改触摸事件逻辑,将触摸数据传递给iOS原生:
<script>
const touchBox = document.getElementById('touchBox');
touchBox.addEventListener('touchstart', function(e) {
e.preventDefault();
const touchInfo = {
type: 'touchstart',
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
// 调用iOS原生注册的方法,传递触摸信息
if (window.webkit && window.webkit.messageHandlers.handleTouchEvent) {
window.webkit.messageHandlers.handleTouchEvent.postMessage(touchInfo);
}
touchBox.innerHTML = '触摸开始,已通知原生';
});
touchBox.addEventListener('touchmove', function(e) {
e.preventDefault();
const touchInfo = {
type: 'touchmove',
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
if (window.webkit && window.webkit.messageHandlers.handleTouchEvent) {
window.webkit.messageHandlers.handleTouchEvent.postMessage(touchInfo);
}
});
touchBox.addEventListener('touchend', function(e) {
e.preventDefault();
const touchInfo = {
type: 'touchend'
};
if (window.webkit && window.webkit.messageHandlers.handleTouchEvent) {
window.webkit.messageHandlers.handleTouchEvent.postMessage(touchInfo);
}
touchBox.innerHTML = '触摸结束,已通知原生';
});
</script>
iOS触摸事件绑定的注意事项
- iOS中默认会对触摸事件有300ms的延迟,若要消除延迟,可以在页面中添加
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">标签,或者在触摸事件中调用e.preventDefault()方法 - 在绑定触摸事件时,尽量避免同时绑定
click事件和触摸事件,防止事件冲突导致响应异常 - 如果需要获取触摸点的坐标,使用
e.touches[0].clientX和e.touches[0].clientY可以获取当前触摸相对于视口的坐标,e.touches[0].pageX和e.touches[0].pageY可以获取相对于页面的坐标 - 在混合应用中,H5调用原生方法时需要先判断
window.webkit.messageHandlers是否存在,避免在非iOS环境下报错
常见问题排查
如果触摸事件没有响应,可以按照以下顺序排查:
- 检查是否正确设置了viewport标签,确保页面没有缩放导致触摸区域偏移
- 检查是否在触摸事件中正确调用了
preventDefault方法,避免被iOS默认行为拦截 - 如果是混合应用,检查WKWebView的配置是否正确,交互方法名是否和H5中调用的名称一致
- 检查是否有其他元素覆盖了触摸区域,导致触摸事件被上层元素拦截