iOS 13 Safari:window.innerHeight中的Bug(们)

7
据我理解,window.innerHeight应该返回视口的大小,不包括浏览器的地址栏、导航栏、选项卡等。但在最新的iOS13中,情况似乎并非如此。存在两个问题:
  1. 有时*竖屏模式下太小)如果从竖屏模式旋转到横屏模式且没有打开标签页,然后再回到竖屏模式,window.innerHeight的值会变得太小(大约是底部导航栏的大小),导致屏幕底部出现可怕的白色条纹。请参阅macrumors上的讨论以获取更多详细信息:https://forums.macrumors.com/threads/is-this-a-mobile-safari-bug-white-space-appears-at-bottom-after-rotating-iphone.2209551/
  2. 有时*横屏模式下太大)如果打开了许多标签,打开了“显示标签栏”,然后从竖屏模式旋转到横屏模式,则window.innerHeight会变得太大,屏幕底部会被裁剪。
即使打开了所有可能的视口标记及其所有排列组合,似乎也没有用。我还查看了若干关于在iOS Safari中处理此问题的“教程”,但到目前为止,我检查过的每个教程都是错误的。
我也尝试了各种window.innerHeight的变化,结果大同小异:
  • 新的可视化视口API返回的结果与window.innerHeight相同。横屏模式下带有选项卡栏的底部仍然被截断,而竖屏模式仍然具有底部白色条纹。
  • document.documentElement.clientHeight使用各种CSS(使用100vh100%等)给出相同的结果。各种div和div元素组合的getBoundingClientRect也是如此。
  • window.outerHeightscreen.height返回完整屏幕大小,不包括浏览器的地址栏、导航栏等,通常太大并导致溢出。
  • 还尝试了其他一些我现在已经忘记的随机方法(应该记笔记),
如果您能猜出顶部和底部浏览器chrome的大小,那么您可以手动修复每个设备的问题,但这非常脆弱。我正在寻找一种不需要构建每个iOS设备和软件配置的巨大查找表的解决方案。
我正在尝试为Web游戏制作全屏画布元素,而这个问题阻碍了我的发货能力。据我所知,这个问题只存在于iOS13中。经过几周的搜索,我仍然没有找到一个好的解决方法。

我们有一个全屏游戏的类似情况。虽然没有涉及JS,但我猜根本原因是相同的。当屏幕从纵向旋转到横向时,一切正常。但有时,当回到纵向时,它会剪切与iOS状态栏高度匹配的屏幕部分(带有时间等)。现在,当我们在纵向上将手机旋转180º(因此底部现在在顶部),它将再次正确计算高度... - Kev
1个回答

1

我最近也遇到了同样的问题,我是这样解决的:

CSS(仅显示相关部分):

html {
    height: 100%;
    min-height: 100%;
    max-height: 100%;
    background: #99f; /* Safari for iOS and Opera for Android in fullscreen mode?!?! */
}

body {
    padding: 0;
    margin: 0;
    color: #000;
    width: 100%; /* I was desperate! This was a wild guess... And worked! */
    height: 100%;
    min-height: 100%;
    max-height: 100%;
    overflow: hidden;
    background: #99f;
}

TypeScript(仅显示相关部分):

// Assume everything here is in the global scope

function detectIOSOrSafari(): boolean {
    // https://dev59.com/EGox5IYBdhLWcg3wr2To
    if ((navigator.userAgent.indexOf("Chrome") <= 0 && navigator.userAgent.indexOf("Safari") >= 0) ||
        (navigator.userAgent.indexOf("Mac") >= 0 && ("ontouchend" in document)))
        return true;
    switch (navigator.platform) {
        case "iPad Simulator":
        case "iPhone Simulator":
        case "iPod Simulator":
        case "iPad":
        case "iPhone":
        case "iPod":
            return true;
    }
    return false;
}

const isIOSOrSafari = detectIOSOrSafari();

function adjustWindowSize(): void {
    let widthCss = window.innerWidth,
        heightCss = window.innerHeight;

    if (document.documentElement && ("clientWidth" in document.documentElement)) {
        widthCss = document.documentElement.clientWidth;
        heightCss = document.documentElement.clientHeight;
    }

    if (isIOSOrSafari) {
        let bodyRect: DOMRect = null;

        // Another act out of desperation...
        if (document.documentElement && ("getBoundingClientRect" in document.documentElement))
            bodyRect = document.documentElement.getBoundingClientRect();
        else if (("getBoundingClientRect" in document.body))
            bodyRect = document.body.getBoundingClientRect();

        if (bodyRect) {
            widthCss = bodyRect.right - bodyRect.left;
            heightCss = bodyRect.bottom - bodyRect.top;
        }
    }

    // Rest of the code, where I use widthCss and heightCss to compute my canvas' size
}

window.onresize = adjustWindowSize;

您可以在项目的存储库中查看整个源代码:https://github.com/carlosrafaelgn/pixel


我认为主要问题来自于视口。当我在iPad上尝试在google.com网站上时,widthCss与window.innerWidth没有区别(纵向)。 - Long Nguyen
@LongNguyen 确实很奇怪。我去年测试过这种情况,遇到的问题与只包含绝对定位元素的主体有关。此外,我只能在几台运行Safari的苹果设备上复制它(感谢BrowserStack)。 - carlosrafaelgn
innerHeight和innerWidth不正确,但它们之间的比例是正确的。因此,在我的iPad上,我假设我的innerWidth等于screen.width,然后我可以轻松地获得正确的innerHeight。 :D - Long Nguyen

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