0

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

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

window.scrollTo(0, 0);

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

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

4

1 回答 1

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,将动画框架用于 rAF polyfill。

于 2014-05-08T16:31:03.317 回答