如果我使用 -webkit-overflow-scrolling,Div 滚动有时会冻结

Posted

技术标签:

【中文标题】如果我使用 -webkit-overflow-scrolling,Div 滚动有时会冻结【英文标题】:Div scrolling freezes sometimes if I use -webkit-overflow-scrolling 【发布时间】:2017-02-03 04:15:27 【问题描述】:

如果我将-webkit-overflow-scrolling 用于滚动 div,它会以原生动量完美滚动。但是,div 本身有时会冻结并且不响应我的手指移动。 2-3 秒后,它再次变为可滚动。

我不知道我是如何重现这个问题的。但是,正如我所见,有两种主要行为造成了这种情况。

首先,如果我等待一段时间,例如 20 秒,然后触摸 div,它没有响应。我等了几秒钟,它又开始工作了。

第二,我快速触摸几次,然后,它变得冻结,然后,几秒钟后,它又开始工作了。

我怎样才能防止这种冻结?

【问题讨论】:

你能试试强制硬件加速吗?例如,如果您的滚动 div 的类在 element 中,请在 CSS 中使用 .element > * -webkit-transform: translateZ(0px); 你能显示你的代码吗?或者链接到问题所在的页面? 所有设备都会出现这种情况吗?还是您遇到此问题的特定设备/浏览器? 你能在帖子中指定你的浏览器和上面的版本吗? 你试过This 【参考方案1】:

对我来说,冻结是可重复的,并且分别在已经位于顶部或底部时尝试向上或向下滚动时发生。解决方法是为touchstarttouchmove 添加一些侦听器,并检测这些情况并在它们上检测event.preventDefault()

类似于以下内容,其中 .scroller 是实际滚动的 div(更改为 scrollTop)。

var lastY = 0;
var targetElt = document.querySelector(".scroller");

targetElt.addEventListener('touchstart', function(event) 
    lastY = event.touches[0].clientY;
);

targetElt.addEventListener('touchmove', function(event) 
    var top = event.touches[0].clientY;

    var scrollTop = event.currentTarget.scrollTop;
    var maxScrollTop = event.currentTarget.scrollHeight -
        $(event.currentTarget).outerHeight();
    var direction = lastY - top < 0 ? 'up' : 'down';

    if (
        event.cancelable && (
            (scrollTop <= 0 && direction === 'up') ||
            (scrollTop >= maxScrollTop && direction === 'down')
        )
    )
      event.preventDefault();

    lastY = top;
);

我希望这对遇到这个可怕错误的下一个可怜的灵魂有所帮助!祝你好运,继续战斗!

【讨论】:

这是最终对我有用的解决方法!在 ios Safari 中打开 live example 并查看 its code。唯一的缺点是当已经在顶部/底部时没有反弹效果,但它是可以接受的,并且似乎是我们拥有的最佳选择,直到 WebKit 维护者修复错误。 @wesley ,我们知道为什么会发生这种情况吗,因为只有在顶部或底部时才会冻结。 @whyAto8 iOS Safari 错误¯_(ツ)_/¯,可能与它在顶部和底部的“反弹”方式有关。关于已经存在的一些东西,它可能会启动反弹效果并且在完成之前没有响应,但由于你已经在那里它只是错误。 @WesleyReitzfeld 好的,知道了。是否与他们一起记录并且他们不想修复它。 @whyAto8 我不知道如何与他们记录。【参考方案2】:

我最近遇到了这个错误,在尝试了很多 hacky 解决方案后,最适合我们的解决方案是简单地将视图滚动一个像素(如果它位于底部)。这可以防止“冻结”,如果嵌套容器完全向下滚动,我认为这实际上是接收滚动事件的主体/窗口。这是使用 React,但你明白了。

const listener = () => 
    window.requestAnimationFrame(() => 
      if (!this.scrollRef.current) 
         return;
      
   
      const  scrollTop, scrollHeight, clientHeight  = this.scrollRef.current;

      if (scrollTop === scrollHeight - clientHeight) 
          // at the bottom
          this.scrollRef.current.scrollTo(0, scrollHeight - clientHeight - 1);
      
    );


this.scrollRef.current.addEventListener("scroll", listener);

【讨论】:

【参考方案3】:

我知道这已经很老了,但也许其他人也有同样的问题。对我来说,这个问题是由 iNoBounce (https://github.com/lazd/iNoBounce) 引起的。 Y 滚动很好,但 X 滚动会导致很多问题,元素会卡住,您必须多次触摸和移动,直到它最终滚动。

删除 iNoBounce 后,除了明显的滚动反弹(特别是“过度滚动”)被 iNoBounce 删除外,其他问题都没有了。为了禁用过度滚动,我使用了以下内容,但是滚动反弹现在在那里。

html  height: 100%; position: fixed; overflow: hidden; 
body  height: 100%; position: relative; overflow: auto; 

【讨论】:

【参考方案4】:

我遇到了同样的问题。但这很容易解决。 这就是我所做的: 删除了可滚动的 div 的高度属性。 也许你和我的情况不同,这对你不起作用。

【讨论】:

【参考方案5】:

尝试在正文上使用overflow: hidden。这应该可以解决问题:https://codepen.io/cppleon/pen/vYOgKzX

HTML

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  </head>
  <body>
    <div id="scrollable-content">
      <div class="site-header"></div>
      <div class="main-content"></div>
    </div>
  </body>
</html>

CSS

body 
  /* magic is here */
  overflow: hidden;


#scrollable-content 
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 50%;
  background-color: gray;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;


.site-header 
  width: 100%;
  height: 120px;
  background-color: orange;


.main-content 
  height: 200%;

【讨论】:

当您在底部或顶部同时点击快速滚动并在滚动完全隐藏时滚动问题消失时,滚动冻结在 iPhone 上不断重现。 overflow: hidden in the body solved my problem【参考方案6】:

稳定的解决方案

经过多日尝试修复,我发现问题来自于已修复的body 元素,可能是因为您不希望您的用户在滚动时看到您的页面正文弹跳被阻止:cf this example。 当身体修复并且您遇到滚动冻结错误时,如果您在 iOS 设备上使用 Desktop Safari 检查身体,您会看到它有点“人为”移动......是的 webkit 东西......

我尝试了有关此威胁的所有解决方案,但也尝试了 github 上的类似问题。没有人在工作。

对我来说唯一稳定的解决方法是使用这个包:body-scroll-lock 和删除body 元素上的fixed。现在你可以同时享受固定的身体和没有滚动冻结的错误。

希望它能帮助目前在 IOS 上创建渐进式网络应用的人们。

【讨论】:

您究竟是如何使用 body-scroll-lock 来防止冻结的? 我将它应用于每个滚动元素【参考方案7】:

我使用了我认为有效的以下代码。

var scrollTimer;
$('.scroller').on('scroll',function(e)
      clearTimeout(scrollTimer);
      scrollTimer = setTimeout(() => 
        this.scrollTop = Math.max(1, Math.min(this.scrollTop, this.scrollHeight - this.clientHeight - 1));
      , 300);
);

【讨论】:

哇:到目前为止,这实际上对我有用。很高兴知道你是怎么做到的。

以上是关于如果我使用 -webkit-overflow-scrolling,Div 滚动有时会冻结的主要内容,如果未能解决你的问题,请参考以下文章

如果我使用 UTF-8,HTML 上的问号字符和 SQL 数据上的奇怪字符,如果我使用 ISO-8859-1 [重复]

如果我使用比较对对象进行排序,如果其中一个对象为零,我如何告诉它不排序?

如果不推荐使用 $(window).load(),我应该使用啥?

如果我使用 mod rewrite,是不是需要使用 ProxyPassReverse?

如果我使用 GridsearchCV,如何在 Xgboost 中使用 model.evals_result()?

如果我使用类似 NHibernate 的 ORM,为啥需要 LINQ?