iPad布局在从竖屏旋转到横屏时会放大。

62

我已经添加了 "viewport" 的元标签 "width=device-width,initial-scale=1.0", 在iPad上,页面在横向模式下加载正常,然后很好地切换到纵向模式。但是,当我将其旋转回横向时,它会将页面缩放并且我必须通过捏合缩放将其缩放回1比例。

我可以通过添加 "maximum-scale=1.0, user-scalable=no" 来解决这个问题,但我想知道是否有一种方法可以在不剥夺用户缩放页面的能力的情况下解决这个问题。

如果你有任何建议,我很乐意听取,
谢谢!


140%的工作还是100%的工作? - PKHunter
11个回答

73

------ 更新 ------

iOS7中不再存在这个问题。Github上Scott Jehl提供了更好的解决方案 scottjehl/iOS-Orientationchange-Fix,适用于iOS6。

------ 原始回答 ------

Jeremy Keith (@adactio)在他的博客《方向和缩放》中有一个很好的解决方案。

保持标记可扩展。

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

然后使用以下脚本在gesturestart事件之前禁用JavaScript可扩展性:

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);
    }
}

谢谢。不过似乎并不是真正的解决方案——iPad 的表现很糟糕,这是他们设计上的问题,我想说。 - Andy
6
这个问题已在iOS6中得到解决。请查看Jeremy Keith在这个问题上的最新帖子:iOS六修复。下面提到的Scott Jehl的修复方法是基于iOS的错误修复而来的。 - Ludder
@Ludder,iOS 6的修复措施可能应该作为一个单独的答案,因为评论很容易被忽略。 - mikl
我在iOS6上使用相同的视口标签。但是我仍然遇到了相同的问题。 - sonam
我在iOS 6下也遇到了同样的问题。 - AJJ
请注意,在Android原生浏览器中,navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)会返回true。 - HandiworkNYC.com

12

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);

1
这里的想法很好,但是因为这个解决方案使用加速度计来预测方向变化,所以有时候如果iPad被倾斜了,它就会无法检测到变化,也就是说,它需要几乎完美地保持竖直才能正常工作。 - Alejo
如果它能检测到以下情况,那么这将是一个更好的解决方案: 1)用户处于竖屏状态,设备相对平放 2)旋转设备而不倾斜 3)将设备向上倾斜以提示设备更改方向用这种方式表达可能听起来不太常见,但我在阅读时经常遇到这种情况。 - bpscott
FYI:(/iPhone|iPad|iPod/.test(navigator.platform) 在 iOS/iPadOS 13(Mobile Safari 13)的桌面模式下已经失效,因为它现在被设置为 MacIntel 在 iOS/iPadOS 上(在 Beta 2 上测试过)。 - robocat

9

希望这能帮到你们,...

<head>

<style type="text/css">
<!--

/*
    I began with the goal to prevent font scaling in Landscape orientation.
    To do this, see: https://dev59.com/KnE85IYBdhLWcg3wkkfK

    Later, I just wanted to magnify font-size for the iPad, leaving
    the iPhone rendering to the css code.  So ...

    (max-device-width:480px) = iphone.css
    (min-device-width:481px) and
        (max-device-width:1024px) and
            (orientation:portrait) = ipad-portrait.css
    (min-device-width:481px) and
        (max-device-width:1024px) and
            (orientation:landscape) = ipad-landscape.css
    (min-device-width:1025px) = ipad-landscape.css

*/

@media only screen and (min-device-width: 481px)
{
    html {
        -webkit-text-size-adjust: 140%;   /* none for no scaling */
    }
}

-->
</style>

</head>

4
哦,有很多提议的JavaScript解决方案,但它仍然会跳来跳去(当您有绝对定位元素等)或禁用缩放或类似的东西。 然后我发现这个简单的CSS解决方案!它可以使旋转平稳且不缩放。这真是太完美了,应该是所有此问题的正确答案!非常感谢@John Love。这绝对是惊人的。 - Steeven
关于你删除的问题 John,当你给别人点反对票时,系统会记录在你的账户里。 - Popnoodles
经过一段时间的思考,我想起很久以前曾经读到一个我认为非常无礼的评论,所以我就找他理论了。我真的很希望能够得到关于这个问题的解释。 - user420479
尝试了none和100%两个值:这在第一次旋转上可以工作,但在随后的旋转中我得到了奇怪的结果(在iOS6模拟器上)。 - David Cook
非常好 - 解决了我的问题,iPhone 5S在横向模式下未正确呈现媒体查询中指定的font-size更改。 - SexxLuthor

3
这里是jQuery Mobile使用的修复方法。 https://github.com/scottjehl/iOS-Orientationchange-Fix 被压缩过的版本。
/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT / GPLv2 License.*/(function (a) { function m() { d.setAttribute("content", g), h = !0 } function n() { d.setAttribute("content", f), h = !1 } function o(b) { l = b.accelerationIncludingGravity, i = Math.abs(l.x), j = Math.abs(l.y), k = Math.abs(l.z), (!a.orientation || a.orientation === 180) && (i > 7 || (k > 6 && j < 8 || k < 8 && j > 6) && i > 5) ? h && n() : h || m() } var b = navigator.userAgent; if (!(/iPhone|iPad|iPod/.test(navigator.platform) && /OS [1-5]_[0-9_]* like Mac OS X/i.test(b) && b.indexOf("AppleWebKit") > -1)) return; var c = a.document; if (!c.querySelector) return; var d = c.querySelector("meta[name=viewport]"), e = d && d.getAttribute("content"), f = e + ",maximum-scale=1", g = e + ",maximum-scale=10", h = !0, i, j, k, l; if (!d) return; a.addEventListener("orientationchange", m, !1), a.addEventListener("devicemotion", o, !1) })(this);

全源代码
/*! A fix for the iOS orientationchange zoom bug.
 Script by @scottjehl, rebound by @wilto.
 MIT / GPLv2 License.
*/
(function(w){

    // This fix addresses an iOS bug, so return early if the UA claims it's something else.
    var ua = navigator.userAgent;
    if( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test(ua) && ua.indexOf( "AppleWebKit" ) > -1 ) ){
        return;
    }

    var doc = w.document;

    if( !doc.querySelector ){ return; }

    var meta = doc.querySelector( "meta[name=viewport]" ),
        initialContent = meta && meta.getAttribute( "content" ),
        disabledZoom = initialContent + ",maximum-scale=1",
        enabledZoom = initialContent + ",maximum-scale=10",
        enabled = true,
        x, y, z, aig;

    if( !meta ){ return; }

    function restoreZoom(){
        meta.setAttribute( "content", enabledZoom );
        enabled = true;
    }

    function disableZoom(){
        meta.setAttribute( "content", disabledZoom );
        enabled = false;
    }

    function checkTilt( e ){
        aig = e.accelerationIncludingGravity;
        x = Math.abs( aig.x );
        y = Math.abs( aig.y );
        z = Math.abs( aig.z );

        // If portrait orientation and in one of the danger zones
        if( (!w.orientation || w.orientation === 180) && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ){
            if( enabled ){
                disableZoom();
            }           
        }
        else if( !enabled ){
            restoreZoom();
        }
    }

    w.addEventListener( "orientationchange", restoreZoom, false );
    w.addEventListener( "devicemotion", checkTilt, false );

})( this );

1

这个可以用!

 <script >
// BUG orientation portrait/lanscape IOS //
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.addEventListener('orientationchange', function () {
        viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1';
    }, false);
  }
}
</script>

1

1
为了让脚本正常工作并绕过第二个手势,需要进行微小调整,比如在方向改变事件中将最大值设置为1.00099而不仅仅是1.0。

0

当你说它扩展页面时,是所有元素还是只有文本字体大小?... 为了修复字体大小,您可以使用:

html {
    -webkit-text-size-adjust: 100%;
}

它会将所有元素放大,基本上只是将页面缩放。 - Victor Ionescu
我进行了修改,使用了100%而不是none,这样可以防止在方向更改时文本大小发生变化,但仍允许用户缩放。您还遇到哪些其他类型的元素问题?我假设某些元素,例如横幅,您希望其宽度具有一定的流动性,但通过CSS控制高度。 - DShultz
我尝试使用webkit-text-size-adjust的100%,但当iPad旋转时,它无法阻止网页缩放不正确。 - IgorGanapolsky
我也有同样的问题(虽然设置文本大小调整很重要),流体网站在启用缩放的情况下,在iPad上从纵向到横向会出现这个问题。这里也有同样的问题:如何在iPhone方向变化时重置Web应用程序的比例/缩放?,但是还没有解决方案适用于我。 - snobojohan

0
第一个修复方法对我有用,但需要进行以下更改。
将初始比例更改为0.8,最小值更改为0.25,最大值更改为1.6。
使用“meta”标签。
<meta name="viewport" content="width=device-width, initial-scale=1">


<script ="text/javascript">
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=.25, maximum-scale=1.6, initial-scale=.8';
        document.body.addEventListener('gesturestart', function () {
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        }, false);
    }
}


0
我提出了一种不同的解决方案,可以在旋转时保持缩放比例为1,但允许用户使用捏合手势缩放。基本上,当用户在进行缩放操作时,JavaScript 会更改视口缩放级别(并禁用本机浏览器的缩放功能)。
在此处查看:https://dev59.com/t3E85IYBdhLWcg3w432o#11878932

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