移动 Safari,scrollIntoView 不起作用

Posted

技术标签:

【中文标题】移动 Safari,scrollIntoView 不起作用【英文标题】:Mobile Safari, scrollIntoView doesn't work 【发布时间】:2017-07-14 08:47:27 【问题描述】:

我在 iframe 中的移动 Safari 上滚动到元素时遇到问题(它适用于其他浏览器,包括 mac 上的 Safari)。

我使用 scrollIntoView。我想在呈现所有 contnet 时滚动。这是我的代码:

var readyStateCheckInterval = setInterval(function () 
    if (document.readyState === "complete") 
       clearInterval(readyStateCheckInterval);
        $browser.notifyWhenNoOutstandingRequests(function () 
            if (cinemaName != null && eventId == null) 
                scrollToCinema();
             else 
                scrollToEvent();
            
        );
     
, 10);


function scrollToEvent() 
    var id = eventId;
    var delay = 100;

    if (cinemaName != null) 
        id = cinemaName + "#" + eventId;
    

    if ($rootScope.eventId != null) 
        id = $rootScope.cinemaId + "#" + $rootScope.eventId;
    

    $timeout(function () 
        var el = document.getElementById(id);
        if (el != null)
        el.scrollIntoView(true);    
        $rootScope.eventId = null;
    , delay);

【问题讨论】:

【参考方案1】:

ScrollIntoView 不起作用(当前)。但是您可以手动计算元素的位置并滚动到它。这是我的解决方案

const element = document.getElementById('myId')

将元素传递给这个函数

/** Scrolls the element into view
 * Manually created since Safari does not support the native one inside an iframe
*/
export const scrollElementIntoView = (element: htmlElement, behavior?: 'smooth' | 'instant' | 'auto') => 

  let scrollTop = window.pageYOffset || element.scrollTop

   // Furthermore, if you have for example a header outside the iframe 
   // you need to factor in its dimensions when calculating the position to scroll to
   const headerOutsideIframe = window.parent.document.getElementsByClassName('myHeader')[0].clientHeight

  const finalOffset = element.getBoundingClientRect().top + scrollTop + headerOutsideIframe

  window.parent.scrollTo(
    top: finalOffset,
    behavior: behavior || 'auto'
  )

陷阱:平滑滚动也不适用于 ios 移动端,但您可以使用 polyfill 补充此代码

【讨论】:

【参考方案2】:

根据我的经验,scrollIntoView() 有时会在我的 iphone 和 ipad 上失败,但有时它可以工作(在我自己的网站上)。我没有使用 iframe。上述设备上的 safari 和 firefox 都是如此。

对我有用的解决方案是弹出您需要滚动到 DIV 中的元素,例如。作为该 DIV 中的第一个元素。嘿,然后它就可以正常工作了! 看起来像是 Apple 的一个狡猾的实现。

【讨论】:

【参考方案3】:

您很可能遇到与我刚刚调试的完全相同的问题。 Safari 会自动调整框架的大小以适应其内容。因此,iframe 的父级将在 Safari 中具有滚动条。因此,从 iframe 本身调用 scrollintoview 会“失败”。

如果 iframe 是跨域通过 window.parent.document 访问父文档将被拒绝。

如果您需要跨域解决方案,请查看我的回答 here.

基本上,我使用发布消息告诉父页面在 Mobile Safari 跨域内进行滚动。

【讨论】:

以上是关于移动 Safari,scrollIntoView 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

js scrollIntoView 滑动问题

scrollIntoView 失效调研与替换方案

scrollIntoView 失效调研与替换方案

scrollIntoView 失效调研与替换方案

关于scrollIntoView和scrollIntoViewIfNeeded

移动端底部input被弹出的键盘遮挡