Safari iPhone - 如何检测缩放级别和偏移量?

21

我正在寻找在iPhone的Safari浏览器中跟踪用户缩放和平移页面的选项。Safari提供了移动和手势事件,理论上我可以不断累加平移和缩放操作,但这似乎有些过度,因为浏览器必须在内部跟踪它们。

这些信息是否通过文档对象模型(DOM)公开?

6个回答

28

当您进行缩放时,window.innerWidth会被调整,但document.documentElement.clientWidth不会调整,因此:

var zoom = document.documentElement.clientWidth / window.innerWidth;

(我已经测试过iOS4,在没有 viewport <meta> 的情况下).

但是,我不会把它用于任何重要的事情。移动浏览器中DOM视口大小/像素大小非常混乱


谢谢。虽然这只是一个小技巧,但听起来似乎真的可行,至少有点希望。 - Jason Kester
3
在这里需要指出的是(或许可以减少一次文件运行),document.documentElement.clientWidth 不包括滚动条,而 window.innerWidth 则包括。高度同理。 - icedwater
忽略滚动条,在Safari 10中,它的变量为:zoom = document.documentElement.clientWidth / window.outerWidth; - uchuugaka
我是指:window.outerWidth / document.documentElement.clientWidth - uchuugaka

3
在移动Safari和Android上,这里有一种准确的方法来测量页面被缩放了多少。请尝试在此处:http://jsbin.com/cobucu/3 - 更改缩放比例然后点击测量。
技术是添加一个顶级div:
<body>
<div id=measurer style="position:absolute;width:100%"></div>

并使用计算:

function getZoom(){
    return document.getElementById('measurer').offsetWidth / window.innerWidth;
}

唯一的问题在于找到一种简洁的方法来检测用户是否更改了缩放比例(例如,捏、双击等)。选项如下:
  • webkitRequestAnimationFrame:非常可靠,但如果使用动画可能会导致不稳定(由于性能损失)
  • setInterval:可靠但非常丑陋
  • 触摸事件:查找两个手指或者双击:丑陋且可能难以100%可靠
  • window.onresize + window.onorientationchange + window.onscroll:简单但完全不可靠(编辑:在WKWebView或Mobile Safari 8或更高版本中,onscroll可能会导致性能问题)。

PS: Windows手机需要不同的解决方案(捏缩不会更改视口 - 在Windows上的捏缩具有自己的独立视口,无法让JavaScript看到)。

编辑:Android视觉视口调整和滚动事件可能有所帮助?请参见https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport#Events


在 iPhone 上测试过,几乎完美地工作。但有时该函数无法检测到缩放,特别是进行大缩放时。 - Sergio

2
根据 Safari Web内容指南,缩放事件(双击)不会被公开,因此我不确定您如何跟踪此事件。我认为这些信息不会通过DOM公开。

1

我认为自史蒂夫的回答以来,事情可能有所进展,因为在查看他提供的内容指南链接时,我可以看到一个关于处理多点触摸事件处理手势事件的部分。

我还没有尝试过它们,但它们看起来非常有前途。一旦我检查完它们并有演示链接可用,我会提供更新...


谷歌快速翻页(http://fastflip.googlelabs.com/)已经实现了这一点,所以肯定是可行的。 - cobbal

0

我用以下方式测量缩放(仅适用于iOS):

screenOrientedWidth = screen.width;
if (window.orientation == 90) {
    screenOrientedWidth = screen.height;
}
return screenOrientedWidth / window.innerWidth;

它不取决于内容有多宽。

然而,在iOS Safari中,window.innerWidthgestureend处理程序内部是不正确的。您应该将此类计算推迟到稍后执行。在GWT中,我使用scheduleDeferred,但是我无法告诉您如何在纯JavaScript中实现这一点。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接