iFrame 中的触摸事件不适用于 iOS
Touch events within iFrame are not working on iOS
touchstart
或 touchend
等触摸事件在 iOS 设备上的 IFrame 内附加到 window 时不会触发。
这是一个非常简单的例子:
parent.html
<!DOCTYPE HTML>
<html style="height: 100%;">
<head>
<meta charset="UTF-8">
<title>Touch Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="height: 100%; margin: 0; overflow: hidden;">
<iframe style="width: 100%; height: 100%; border: none;" src="child.html"></iframe>
</body>
</html>
child.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Touch Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
padding: 8px;
}
div.header {
margin-bottom: 8px;
}
div.text-entry {
font: 300 1rem/1.25 'Open Sans', 'Helvetica Neue', helvetica, arial, sans-serif;
color: rgb(64, 64, 64);
}
</style>
<script>
window.onload = function() {
function addEvent(event) {
var div = document.createElement('div');
div.className = 'text-entry';
div.textContent = new Date().toLocaleTimeString() + ' Event "' + event.type + '" detected';
document.body.appendChild(div);
}
window.addEventListener('touchstart', addEvent.bind(null), false);
window.addEventListener('touchend', addEvent.bind(null), false);
}
</script>
</head>
<body>
<div class="text-entry header">Clicks/touches on the viewport should add some text entries...</div>
</body>
</html>
我发现了多个关于 iOS 在 IFrames 中的滚动问题和一些关于事件的问题,但是 none 似乎有一个有效的解决方案来解决我现在遇到的问题。
我创建了一个 CodePen and a JSFiddle 供大家玩,它显示了完全相同的行为,因为两者都在 IFrame 中执行代码。
将以下 CSS 添加到 IFrame 内容(在我上面的示例中为 child.html)解决了我的问题:
html, body {
touch-action: auto;
}
解决方案一:
在 iframe 中,将虚拟侦听器添加到 document 对象:
document.addEventListener('touchstart', {}); // in iframe
IOS 上的 Safari 似乎拒绝 window 的触摸监听器,除非其他 DOM 对象也有监听器。
方案二:
在顶部 window 内,为任何对象添加一个虚拟侦听器(包括 window):
window.addEventListener('touchstart', {}); // in top window
IOS 上的 Safari 似乎拒绝 iframe 中 window 的触摸监听器,除非父级也有监听器。
以上解决方案中的任何一个都有效(不需要同时使用它们,只需要一个)。
测试于:
- 野生动物园 9.0/IOS: 9.3.5
- 野生动物园 11.0 / IOS: 11.3
touchstart
或 touchend
等触摸事件在 iOS 设备上的 IFrame 内附加到 window 时不会触发。
这是一个非常简单的例子:
parent.html
<!DOCTYPE HTML>
<html style="height: 100%;">
<head>
<meta charset="UTF-8">
<title>Touch Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="height: 100%; margin: 0; overflow: hidden;">
<iframe style="width: 100%; height: 100%; border: none;" src="child.html"></iframe>
</body>
</html>
child.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Touch Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
padding: 8px;
}
div.header {
margin-bottom: 8px;
}
div.text-entry {
font: 300 1rem/1.25 'Open Sans', 'Helvetica Neue', helvetica, arial, sans-serif;
color: rgb(64, 64, 64);
}
</style>
<script>
window.onload = function() {
function addEvent(event) {
var div = document.createElement('div');
div.className = 'text-entry';
div.textContent = new Date().toLocaleTimeString() + ' Event "' + event.type + '" detected';
document.body.appendChild(div);
}
window.addEventListener('touchstart', addEvent.bind(null), false);
window.addEventListener('touchend', addEvent.bind(null), false);
}
</script>
</head>
<body>
<div class="text-entry header">Clicks/touches on the viewport should add some text entries...</div>
</body>
</html>
我发现了多个关于 iOS 在 IFrames 中的滚动问题和一些关于事件的问题,但是 none 似乎有一个有效的解决方案来解决我现在遇到的问题。
我创建了一个 CodePen and a JSFiddle 供大家玩,它显示了完全相同的行为,因为两者都在 IFrame 中执行代码。
将以下 CSS 添加到 IFrame 内容(在我上面的示例中为 child.html)解决了我的问题:
html, body {
touch-action: auto;
}
解决方案一: 在 iframe 中,将虚拟侦听器添加到 document 对象:
document.addEventListener('touchstart', {}); // in iframe
IOS 上的 Safari 似乎拒绝 window 的触摸监听器,除非其他 DOM 对象也有监听器。
方案二: 在顶部 window 内,为任何对象添加一个虚拟侦听器(包括 window):
window.addEventListener('touchstart', {}); // in top window
IOS 上的 Safari 似乎拒绝 iframe 中 window 的触摸监听器,除非父级也有监听器。
以上解决方案中的任何一个都有效(不需要同时使用它们,只需要一个)。 测试于:
- 野生动物园 9.0/IOS: 9.3.5
- 野生动物园 11.0 / IOS: 11.3