禁用视图缩放 iOS10 + Safari?

我已经把我的 iPhone6 + 升级到了 iOS10 beta 版本,并且发现在移动 Safari 中,你可以通过双击或者捏一下 meta 标签中的 user-scalable=no代码来缩放任何网页。我不知道这是一个 bug 还是一个特性。如果它被认为是一个特性,我们如何禁用视窗缩放 iOS10狩猎?


更新于 iOS11/12版本,iOS11和 iOS12 Safari 仍然做 没有尊重 user-scalable=no元标签。

mobile github site on Safari

145764 次浏览

这是 iOS10的一个新特性。

来自 iOS 10 beta 1发布说明:

  • 为了提高 Safari 中网站的可访问性,用户现在甚至可以在网站在视窗中设置 user-scalable=no时进行手指缩放。

我希望我们很快就会看到一个 JS 附加组件来以某种方式禁用它。

在 iOS10中防止 Safari 中的网页扩展是可能的,但是这将涉及到你更多的工作。我猜想,一定程度的困难应该阻止货物崇拜开发人员将“用户可伸缩 = 否”放入每个视窗标签,并使视力受损用户的事情变得不必要的困难。

尽管如此,我希望看到苹果改变他们的实现,以便有一个简单的(元标记)方式来禁用双击缩放。大多数困难都与这种互动有关。

你可以用这样的东西停止手指缩放:

document.addEventListener('touchmove', function (event) {
if (event.scale !== 1) { event.preventDefault(); }
}, false);

请注意,如果任何更深层的目标对事件调用 stop 傳播,则事件将不会到达文档,并且此侦听器不会阻止缩放行为。

禁用双击缩放也是类似的。禁用任何在前一次点击300毫秒内发生的对文档的点击:

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
var now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);

如果没有正确设置表单元素,将焦点集中在输入上将自动缩放,并且由于您基本上禁用了手动缩放,因此现在几乎不可能取消缩放。确保输入字体大小 > = 16px。

如果您试图在本地应用程序的 WKWebView 中解决这个问题,上面给出的解决方案是可行的,但这是一个更好的解决方案: https://stackoverflow.com/a/31943976/661418。正如在其他答案中提到的,在 iOS10Beta6中,苹果现在提供了一个标志来纪念 meta 标签。

2017年5月更新: 我用一个更简单的“ check events. scale on touch move”方法取代了旧的“ check touch length on touch start”方法,即禁用按压缩放。对每个人来说都应该更可靠。

似乎这种行为在最新的测试版本中被改变了,在写这篇文章的时候这个版本还是测试版6。

IOS10Beta 6的发布说明:

WKWebView现在默认从一个 viewport 尊重 user-scalable=noWKWebView的客户端可以提高可访问性,并允许用户 通过设置 WKWebViewConfiguration对所有页面进行按压缩放 属性 ignoresViewportScaleLimitsYES

然而,在我(非常有限的)测试中,我还不能确认这是否属实。

编辑: 验证,iOS10Beta 6尊重 user-scalable=no默认为我。

我尝试了前一个关于缩放的答案

document.documentElement.addEventListener('touchstart', function (event) {
if (event.touches.length > 1) {
event.preventDefault();
}
}, false);

但是,有时当 < strong > events. touch es.length > 1时,屏幕仍然会放大 我发现最好的方法是使用触摸事件,以避免任何手指在屏幕上移动。代码是这样的:

document.documentElement.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);

希望能有所帮助。

我花了大约一个小时寻找一个更健壮的 javascript 选项,但是没有找到。碰巧的是,在过去的几天里,我一直在摆弄 锤子 Js(Hammer.js 是一个可以让你轻松操作各种触摸事件的库) ,而且大多数时候我尝试做的事情都失败了。

说明一下,我并不是一个 javascript 专家,这是我想出来的一个解决方案,它基本上利用 hammer.js 捕获捏缩和双击事件,然后记录并丢弃它们。

确保你在你的页面中包含了 hammer.js,然后试着把这个 javascript 放在你的头脑中的某个地方:

< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >


// SPORK - block pinch-zoom to force use of tooltip zoom
$(document).ready(function() {


// the element you want to attach to, probably a wrapper for the page
var myElement = document.getElementById('yourwrapperelement');
// create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
var hammertime = new Hammer(myElement, {
prevent_default: false,
touchAction: "pan"
});


// pinch is not enabled by default in hammer
hammertime.get('pinch').set({
enable: true
});


// name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
console.log('captured event:', e.type);
e.preventDefault();
})
});
</script>

检查触摸事件中的比例因子,然后防止触摸事件。

document.addEventListener('touchmove', function(event) {
event = event.originalEvent || event;
if(event.scale > 1) {
event.preventDefault();
}
}, false);

听起来很奇怪,至少对于 iOS10.2中的 Safari 来说,如果你的元素或者它的任何一个祖先拥有以下特性之一,那么双击缩放就会被神奇地禁用:

  1. 一个 onClick 监听器-它可以是一个简单的 noop。
  2. 用 CSS 设置的 cursor: pointer

我已经能够使用单个元素上的 touch-action css 属性修复这个问题。尝试对通常单击的元素(如链接或按钮)设置 touch-action: manipulation;

我在我的 iOS 页面(iPhone6,iOS10.0.2)上实际检查了以上所有答案,但没有成功。这是我的工作解决方案:

$(window).bind('gesturestart touchmove', function(event) {
event = event.originalEvent || event;
if (event.scale !== 1) {
event.preventDefault();
document.body.style.transform = 'scale(1)'
}
});

无意识的 放大往往发生在以下情况:

  • 用户双击接口的组件
  • 用户使用两个或多个数字(捏)与视口交互

为了防止 双击的行为,我找到了两个非常简单的解决办法:

<button onclick='event.preventDefault()'>Prevent Default</button>
<button style='touch-action: manipulation'>Touch Action Manipulation</button>

这些都阻止 Safari (iOS10.3.2)从 放大进入按钮。正如你所看到的,一个只是 JavaScript,另一个只是 CSS。正确使用。

这里是一个演示: https://codepen.io/lukejacksonn/pen/QMELXQ

我还没有试图阻止捏操作,主要是因为我倾向于不为网页创建多点触摸界面,其次我已经转变了想法,也许所有的界面,包括本地应用程序界面应该是“捏缩”-能够在某些地方。我仍然设计避免用户 拥有这样做,以使您的 UI 对他们可访问,不惜一切代价。

我们可以通过注入一个样式规则和拦截缩放事件来获得我们想要的一切:

$(function () {
if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
$(document.head).append(
'<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
)
$(window).on('gesturestart touchmove', function (evt) {
if (evt.originalEvent.scale !== 1) {
evt.originalEvent.preventDefault()
document.body.style.transform = 'scale(1)'
}
})
})

Something 禁用捏缩。

Something 禁用双击缩放。

Something 卷轴不受影响。

Something 禁用点击突出显示(在 iOS 上通过样式规则触发)。

注意: 调整 iOS 检测到你的喜好。更多关于 给你


LukejacksonPiotr Kowalski表示歉意,它们的答案以修改后的形式出现在上面的代码中。

找到了这个简单的工作,似乎可以防止双击放大:

    // Convert touchend events to click events to work around an IOS 10 feature which prevents
// developers from using disabling double click touch zoom (which we don't want).
document.addEventListener('touchend', function (event) {
event.preventDefault();
$(event.target).trigger('click');
}, false);

我想出了一个非常天真的解决方案,但似乎奏效了。 我的目标是防止意外的双击被解释为放大,同时保持捏放大工作的可访问性。

这个想法是在测量时间之间的第一个 touchstart和第二个 touchend在双击,然后解释最后的 touchend作为点击,如果延迟太小。在防止意外缩放的同时,这种方法似乎保持列表滚动不受影响,这很好。不知道我是不是错过了什么。

let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;


document.addEventListener('touchstart', () => {
preLastTouchStartAt = lastTouchStartAt;
lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
const touchEndAt = +new Date();
if (touchEndAt - preLastTouchStartAt < delay) {
event.preventDefault();
event.target.click();
}
});

灵感来自 冬季静音的要点约瑟夫的回答

在我的个例中,我使用 Babylon.js 创建一个3D 场景,我的整个页面由一个全屏画布组成。3D 引擎有自己的缩放功能,但在 iOS 系统上,手指缩放功能会干扰这一功能。我更新了“约瑟夫”的回答来克服我的问题。为了禁用它,我发现需要将{ sive: false }作为一个选项传递给事件侦听器。以下代码适用于我:

window.addEventListener(
"touchmove",
function(event) {
if (event.scale !== 1) {
event.preventDefault();
}
},
{ passive: false }
);

在编写本文时,Mobile Safari 中的解决方案是将 addEventListener中的第三个参数设置为 { passive: false },因此完整的解决方案看起来如下:

document.addEventListener('touchmove', function (event) {
if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

您可能希望 检查是否支持选项保持向后兼容。

这招对我很管用:

document.documentElement.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);

按照要求,我已经将我的评论转换成了一个答案,这样人们就可以对它进行更正:

在 iOS13中,90% 的情况都是这样:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" />

还有

<meta name="HandheldFriendly" content="true">

在当前版本的 Safari 中,这已经不再有效了。必须通过传递{ passv: false }将第二个参数定义为非被动的

 document.addEventListener('touchmove', function(e) {
e.preventDefault();
}, { passive: false });

使用“触摸动作: pan-x pan-y”来禁用“捏缩放”和“双击缩放”。它适用于我测试过的所有触摸屏/手机,包括 iOSSafari 14.5.1。

body {
touch-action: pan-x pan-y;
}