【问题标题】:Scroll position jumps if DOM is changed while elastic scroll is bouncing如果在弹性滚动弹跳时更改 DOM,则滚动位置会跳转
【发布时间】:2014-06-26 04:14:11
【问题描述】:

在 OS X 上,用户可以滚动查看视口,浏览器会弹回页面。
作为用户,我喜欢这种效果,但它会导致我们网站出现不幸的错误。

当用户点击页面底部的“下一篇”大横幅时,会加载下一篇文章并替换页面上的大部分 DOM。发生这种情况时,我将滚动位置重置为顶部:

window.scrollTo(0, 0);

这通常可以正常工作。但是,如果用户在浏览器因弹性滚动而弹跳页面时点击“下一篇文章”scrollTo 将无法正常工作。似乎在替换了大部分 DOM 并重置滚动位置之后,弹跳效果中的一些剩余事件“到达”并使滚动在 重置为零之后跳到下方一两个屏幕。 p>

如何强制浏览器滚动到开头并忽略剩余的弹跳事件?
这发生在 WebKit 上。

【问题讨论】:

    标签: javascript macos webkit scroll browser-bugs


    【解决方案1】:

    我无法解决这个问题,因此作为一种解决方法,我编写了一个返回承诺的函数。这个承诺在弹性滚动完成后解决。

    当用户点击“下一篇文章”时,我会加载文章,但我会等到 promise 解决后再执行 DOM 操作并调用scrollTo。这对我很有效。

    function waitForElasticScroll() {
    
      // If user scrolls part viewport and clicks while elastic scroll
      // has not fully "returned", scroll position will get messed up in Chrome.
    
      // Our workaround is to wait for elastic scroll to finish before transitioning.
      // rAF calls help avoid unnecessary layout.
    
      return new Promise(function (resolve) {
        window.requestAnimationFrame(function () {
          var maxScrollY = document.body.scrollHeight - window.innerHeight;
    
          function isReady() {
            var scrollY = window.scrollY || window.pageYOffset;
            return scrollY <= maxScrollY;
          }
    
          function resolveIfReady() {
            if (isReady()) {
              resolve();
            } else {
              window.requestAnimationFrame(resolveIfReady);
            }
          }
    
          resolveIfReady();
    
        });
      });
    }
    

    我将 Bluebird 用于 Promises,animation-frame 用于 rAF polyfill。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 2020-10-15
      • 2020-07-31
      • 2021-12-26
      • 1970-01-01
      相关资源
      最近更新 更多