如何在iPhone上更改方向更改时重置Web应用程序的缩放比例/缩放比例?

问题描述:

当我在纵向模式下启动我的应用程序时,它工作正常。然后,我旋转到风景,并放大。为了使它在横向模式下正确缩放,我必须双击两次,第一次放大(正常的双击行为),再次放大(再次,正常的双击行为) 。当它缩小时,它缩小到横向模式的正确的新比例。如何在iPhone上更改方向更改时重置Web应用程序的缩放比例/缩放比例?

切换回肖像似乎工作更一致;也就是说,它会处理缩放,以便在方向更改为纵向时缩放比例正确。

我想弄清楚这是一个错误吗?或者如果这是可以用JavaScript修复的东西?

对于视口元内容,我将初始缩放设置为1.0,而不是设置最小或最大缩放比例(我也不想)。我将宽度设置为设备宽度。

任何想法?我知道很多人会很感激拥有解决方案,因为它似乎是一个持续存在的问题。

+1

完美的解决方案:没有JavaScript! http://stackoverflow.com/a/8727440/805787 – Steeven 2012-06-05 09:41:53

杰里米·基思()有这是他的博客上的一个很好的解决方案Orientation and scale

通过不在标记中设置最大比例来保持标记的可缩放性。

<meta name="viewport" content="width=device-width, initial-scale=1"> 

然后禁用与负载JavaScript的可扩展性,直到gesturestart当你再次允许可扩展性,此脚本:

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) { 
    var viewportmeta = document.querySelector('meta[name="viewport"]'); 
    if (viewportmeta) { 
     viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0'; 
     document.body.addEventListener('gesturestart', function() { 
      viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6'; 
     }, false); 
    } 
} 

更新22-12-2014:
上iPad 1这不起作用,它在eventlistener上失败。我发现,消除.body修补程序:

document.addEventListener('gesturestart', function() { /* */ }); 
+4

这肯定比禁用缩放更好?!我找到了最好的修复:) – danwellman 2011-09-23 13:58:45

+0

这也适用于我。谢谢! – 29er 2011-10-31 04:30:43

+0

嗯,这仍然禁用缩放功能。有没有人有一个简单的解决方案,不这样做? – 2012-02-20 07:00:51

MobileSafari支持window对象上的orientationchange事件。不幸的是,似乎没有办法通过JavaScript直接控制缩放。也许你可以动态地编写/更改控制视口的meta标签 - 但我怀疑这会起作用,它只会影响页面的初始状态。也许你可以使用这个事件来实际调整你的内容使用CSS。祝你好运!

+3

谢谢!是的,我尝试动态更改元标记视口值,它什么也没做。 在我看来,如果旋转到横向,您希望它能够正确缩放以保持缩放比例,以便页面适合Safari窗口。对我来说这似乎很奇怪,这不是默认行为! – Elisabeth 2010-04-01 03:08:11

我有同样的问题,并设置最大规模= 1.0为我工作。

编辑: 正如在评论中提到的,除非内容超出宽度分辨率,否则禁用用户缩放。如前所述,这可能不是明智之举。在某些情况下也可能需要。

的视域代码:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;"> 
+0

谢谢,我会试试看! – Elisabeth 2010-05-08 04:42:47

+0

不错的解决方案。通过改变方向,将页面保持在恒定缩放级别(相对于设备的宽度)方面做得很好。感谢分享! – 2011-04-19 15:16:07

+17

不利的一面是,禁用的用户无法在您的网站上放大! – 2011-05-17 17:48:50

如果您有宽度在视口中设置:

<meta name = "viewport" content = "width=device-width; initial-scale=1.0; 
maximum-scale=1.0;" /> 

,然后改变它会随机放大有时(特别是如果你是拖在方向屏幕)来解决这个在这里不设置宽度我用:

<meta id="viewport" name="viewport" content="initial-scale=1.0; user-scalable=0; 
minimum-scale=1.0; maximum-scale=1.0" /> 

这修复了放大所发生的任何事情,然后你可以使用window.onorientationchange事件,或者如果你希望它是平台独立的(方便测试)window.innerWidth方法。

<meta name="viewport" id="view" content="user-scalable=yes, width=device-width minimum-scale=1, maximum-scale=1" /> 

接下来,你可以通过JavaScript调用:

伊丽莎白您可以通过添加 “ID” 属性的元标记动态地改变视内容

document.getElementById("view").setAttribute('content','user-scalable=yes, width=device-width, minimum-scale=1, maximum-scale=10'); 
+0

@bridgestew如果你想改变缩放或视口dinamically使用子视图滚动视图包含到uiwebview。在其他线程添加示例snipet:[链接](http://stackoverflow.com/questions/2890673/iphone-uiwebview-width-does-not-fit -after-zooming-operation-uiinterfaceorientat/5015129#5015129) – 2011-02-17 09:02:56

+4

@伊丽莎白能为你工作吗?切换横向模式时,它不会重置缩放。 – 2011-04-20 17:36:16

+1

不,不适用于我。 – Elisabeth 2012-05-13 17:45:31

我创建了一个横向/纵向布局的工作演示,但变焦必须禁用为它没有JavaScript的工作:

http://matthewjamestaylor.com/blog/ipad-layout-with-landscape-portrait-modes

Scott Jehl想出了一个奇妙的解决方案,它使用加速度计来预测方位变化。此解决方案非常灵敏,不会干扰缩放手势。

https://github.com/scottjehl/iOS-Orientationchange-Fix

工作原理:该修复工程通过监听设备的 加速度计来预测何时取向的变化即将发生。 当它认为即将进行方向更改时,该脚本将禁用用户 缩放,允许方向更改正确进行,禁用 缩放。一旦设备 的方向接近直立,或者其方向已更改 后,脚本将再次恢复缩放。这样,在页面处于 的使用中,用户缩放永远不会被禁用。

精缩来源:

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT License.*/(function(m){if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1)){return}var l=m.document;if(!l.querySelector){return}var n=l.querySelector("meta[name=viewport]"),a=n&&n.getAttribute("content"),k=a+",maximum-scale=1",d=a+",maximum-scale=10",g=true,j,i,h,c;if(!n){return}function f(){n.setAttribute("content",d);g=true}function b(){n.setAttribute("content",k);g=false}function e(o){c=o.accelerationIncludingGravity;j=Math.abs(c.x);i=Math.abs(c.y);h=Math.abs(c.z);if(!m.orientation&&(j>7||((h>6&&i<8||h<8&&i>6)&&j>5))){if(g){b()}}else{if(!g){f()}}}m.addEventListener("orientationchange",f,false);m.addEventListener("devicemotion",e,false)})(this); 
+0

不错!看起来像一个优雅的解决方案。 – Elisabeth 2012-05-13 17:44:47

+1

这应该是被接受的答案!我希望我先看到了这一点,然后浪费了一小时以上的解决方案:) – tmsimont 2012-06-01 21:55:42

+1

进一步测试后,这是一种不可靠的解决方案:(它不一致,并通过代码后,我可以看到为什么...“阈值”定义的运动不总是达到,特别是如果你在旋转的时候拿着一个角度的ipad – tmsimont 2012-06-06 17:56:43

我已经找到了新的解决方法,其他任何不同,我所看到的,通过禁用机iOS变焦,并在JavaScript不是实现缩放功能。

SérgioLopes:A fix to the famous iOS zoom bug on orientation change to portrait有关各种其他缩放/定位问题解决方案的出色背景。

<!DOCTYPE html> 
<html> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <meta name="viewport" id="viewport" content="user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" /> 
    <title>Robocat mobile Safari zoom fix</title> 
    <style> 
     body { 
      padding: 0; 
      margin: 0; 
     } 
     #container { 
      -webkit-transform-origin: 0px 0px; 
      -webkit-transform: scale3d(1,1,1); 
      /* shrink-to-fit needed so can measure width of container http://stackoverflow.com/questions/450903/make-css-div-width-equal-to-contents */ 
      display: inline-block; 
      *display: inline; 
      *zoom: 1; 
     } 
     #zoomfix { 
      opacity: 0; 
      position: absolute; 
      z-index: -1; 
      top: 0; 
      left: 0; 
     } 
    </style> 
</head> 

<body> 
    <input id="zoomfix" disabled="1" tabIndex="-1"> 
    <div id="container"> 
     <style> 
      table { 
       counter-reset: row cell; 
       background-image: url(http://upload.wikimedia.org/wikipedia/commons/3/38/JPEG_example_JPG_RIP_010.jpg); 
      } 
      tr { 
       counter-increment: row; 
      } 
      td:before { 
       counter-increment: cell; 
       color: white; 
       font-weight: bold; 
       content: "row" counter(row) ".cell" counter(cell); 
      } 
     </style> 
     <table cellspacing="10"> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
      <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td> 
     </table> 
    </div> 

    <script> 
    (function() { 
     var viewportScale = 1; 
     var container = document.getElementById('container'); 
     var scale, originX, originY, relativeOriginX, relativeOriginY, windowW, windowH, containerW, containerH, resizeTimer, activeElement; 
     document.addEventListener('gesturestart', function(event) { 
      scale = null; 
      originX = event.pageX; 
      originY = event.pageY; 
      relativeOriginX = (originX - window.pageXOffset)/window.innerWidth; 
      relativeOriginY = (originY - window.pageYOffset)/window.innerHeight; 
      windowW = window.innerWidth; 
      windowH = window.innerHeight; 
      containerW = container.offsetWidth; 
      containerH = container.offsetHeight; 
     }); 
     document.addEventListener('gesturechange', function(event) { 
      event.preventDefault(); 
      if (originX && originY && event.scale && event.pageX && event.pageY) { 
       scale = event.scale; 
       var newWindowW = windowW/scale; 
       if (newWindowW > containerW) { 
        scale = windowW/containerW; 
       } 
       var newWindowH = windowH/scale; 
       if (newWindowH > containerH) { 
        scale = windowH/containerH; 
       } 
       if (viewportScale * scale < 0.1) { 
        scale = 0.1/viewportScale; 
       } 
       if (viewportScale * scale > 10) { 
        scale = 10/viewportScale; 
       } 
       container.style.WebkitTransformOrigin = originX + 'px ' + originY + 'px'; 
       container.style.WebkitTransform = 'scale3d(' + scale + ',' + scale + ',1)'; 
      } 
     }); 
     document.addEventListener('gestureend', function() { 
      if (scale && (scale < 0.95 || scale > 1.05)) { 
       viewportScale *= scale; 
       scale = null; 
       container.style.WebkitTransform = ''; 
       container.style.WebkitTransformOrigin = ''; 
       document.getElementById('viewport').setAttribute('content', 'user-scalable=no,initial-scale=' + viewportScale + ',minimum-scale=' + viewportScale + ',maximum-scale=' + viewportScale); 
       document.body.style.WebkitTransform = 'scale3d(1,1,1)'; 
       // Without zoomfix focus, after changing orientation and zoom a few times, the iOS viewport scale functionality sometimes locks up (and completely stops working). 
       // The reason I thought this hack would work is because showing the keyboard is the only way to affect the viewport sizing, which forces the viewport to resize (even though the keyboard doesn't actually get time to open!). 
       // Also discovered another amazing side effect: if you have no meta viewport element, and focus()/blur() in gestureend, zoom is disabled!! Wow! 
       var zoomfix = document.getElementById('zoomfix'); 
       zoomfix.disabled = false; 
       zoomfix.focus(); 
       zoomfix.blur(); 
       setTimeout(function() { 
        zoomfix.disabled = true; 
        window.scrollTo(originX - relativeOriginX * window.innerWidth, originY - relativeOriginY * window.innerHeight); 
        // This forces a repaint. repaint *intermittently* fails to redraw correctly, and this fixes the problem. 
        document.body.style.WebkitTransform = ''; 
       }, 0); 
      } 
     }); 
    })(); 
    </script> 
</body> 
</html> 

它可以改进,但我需要它避免了与我见过的所有其他解决方案发生重大缺陷。到目前为止,我只在iOS 4上的iPad 2上使用移动Safari进行了测试。

focus()/ blur()是一种解决方法,用于防止在改变方向和缩放几次后偶尔会出现缩放功能的锁定。

设置document.body.style将强制进行全屏重画,以避免在缩放后重绘失败时偶尔出现间歇性问题。

我一直在我的项目中使用这个功能。

function changeViewPort(key, val) { 
    var reg = new RegExp(key, "i"), oldval = document.querySelector('meta[name="viewport"]').content; 
    var newval = reg.test(oldval) ? oldval.split(/,\s*/).map(function(v){ return reg.test(v) ? key+"="+val : v; }).join(", ") : oldval+= ", "+key+"="+val ; 
    document.querySelector('meta[name="viewport"]').content = newval; 
} 

所以才的addEventListener:

if(/iPad|iPhone|iPod|Android/i.test(navigator.userAgent)){ 
    window.addEventListener("orientationchange", function() { 
     changeViewPort("maximum-scale", 1); 
     changeViewPort("maximum-scale", 10); 
    } 
} 

这里是另一种方式来做到这一点,这似乎运作良好。

  1. 设置元标记,以限制视口是按比例= 1,从而防止变焦:

    <阶name = “视口” 内容=“宽度=设备宽度,初始规模= 1,最小规模= 1,最大规模= 1 “>

  2. 用JavaScript,改变元标记1/2秒以后 允许缩放:

    的setTimeout(函数(){document.querySelector(”元[名称=视口]“)。的setAttribute( '内容',” width = device-width,initial-scale = 1');},500);

  3. 与JavaScript

    同样,上朝向的变化,重新加载该页面:

    window.onorientationchange =函数(){window.location.reload();};

每次重新调整设备的方向时,页面都会重新加载,最初不会缩放。但1/2秒后,缩放能力恢复。

+4

在问了5年之后回答一个问题就是...... 不幸的是,这不是网络在2015年的工作方式。用户旋转他的设备。 – Pierre 2015-06-30 14:36:19

找到一个很容易实现的修复程序。完成表单时,将焦点设置为字体大小为50px的文本元素。如果文本元素被隐藏,但似乎不起作用,但通过将元素颜色属性设置为不透明,可以轻松隐藏此元素。