在iOS Safari上,屏幕旋转后window.scrollTo无法正常工作。

3

简而言之:

在iOS Safari中,如果从orientationchange事件处理程序调用window.scrollTo方法,则不会有任何作用。在方向改变后,似乎必须经过一定的时间(500-1000毫秒)才能修改滚动位置。

是否有解决方法可以立即更改滚动位置并避免用户在方向更改后短暂地看到旧的滚动位置的问题?

详细的问题描述:

我需要为移动浏览器实现以下功能:

当用户切换到横屏模式时,他应该看到全屏视频。当他切换回竖屏时,应恢复到离开时的确切位置。

第二部分是问题所在。仅当您不滚动屏幕且不对DOM进行任何调整时,iOS和Android才会保留滚动位置。因此,如果您只是从纵向切换到横向然后返回,一切都如预期的那样。如果您从纵向切换到横向,即使只调整1像素的滚动位置或对DOM进行任何更改,也将返回到不同的滚动位置。

因此,我正在尝试在用户返回到纵向方向时自动恢复滚动位置。这是我使用的简化代码:

    var scrollPosition;
    var savedScrollPosition;

    window.addEventListener('scroll', function() {
        scrollPosition = window.scrollY;
    });

    window.addEventListener('orientationchange', function(event) {
        if (Math.abs(window.orientation) === 90) {
            // This line will correctly save last scroll position for portrait orientation
            savedScrollPosition = scrollPosition;
        } else {
            // This line will correctly try to restore previously saved scroll position
            window.scrollTo(0, savedScrollPosition);
        }
    });

这个在安卓系统上可以工作,但是在iOS系统上不行。问题在于,在方向改变之后的一段时间内,window.scrollTo似乎根本没有起到任何效果。

因此,如果我改变

window.scrollTo(0, savedScrollPosition);

为了

setTimeout(function() {
    window.scrollTo(0, savedScrollPosition);
}, 1000);

这个功能在iOS上可以正常使用,但用户会在短暂的时间里看到页面的错误部分,这导致用户体验较差。

我希望有人知道一种方法,在方向改变事件后立即更改iOS上的滚动位置。

谢谢。


超时时间少了会发生什么?比如说100。 - Rayon
@Rayon 没有任何效果。窗口保持正常位置,没有任何 scrollTo 调用。大约在 500ms 左右,您才有 50/50 的机会实际更改滚动。当然,有一种解决方案可以通过设置 10ms 的间隔来加快结果,调用 scrollTo,然后检查 window.scrollY 是否已更改。但是,无论间隔多小,用户仍将在短暂时间内看到无效位置。 - Alexey
你正在运行最新的iOS吗?我模糊地记得在相对较近的版本中引入并修复了一些方向问题,但我不知道它们是否包括你所经历的问题。 - DBS
1个回答

4
最终,我被迫使用以下代码:
var scrollPosition;
var savedScrollPosition;

window.addEventListener('scroll', function() {
    scrollPosition = window.scrollY;
});

window.addEventListener('orientationchange', function(event) {
    if (Math.abs(window.orientation) === 90) {
        savedScrollPosition = scrollPosition;
    } else {
        if (isIOS()) {
            var retryScroll = setInterval(function () {
                if (window.scrollX === 0 && window.scrollY == savedScrollPosition) {
                    clearInterval(retryScroll);
                } else {
                    window.scrollTo(0, savedScrollPosition);
                }
            }, 10 );
        } else {
            window.scrollTo(0, savedScrollPosition);
        }
    }
});

用户会看到一个小的视觉故障,但这仍然是最佳解决方案。

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