如果在弹性滚动弹跳时更改 DOM,则滚动位置会跳转
Posted
技术标签:
【中文标题】如果在弹性滚动弹跳时更改 DOM,则滚动位置会跳转【英文标题】:Scroll position jumps if DOM is changed while elastic scroll is bouncing 【发布时间】:2014-06-26 04:14:11 【问题描述】:在 OS X 上,用户可以滚动查看视口,浏览器会弹回页面。 作为用户,我喜欢这种效果,但它会导致我们网站出现不幸的错误。
当用户点击页面底部的“下一篇”大横幅时,会加载下一篇文章并替换页面上的大部分 DOM。发生这种情况时,我将滚动位置重置为顶部:
window.scrollTo(0, 0);
这通常可以正常工作。但是,如果用户在浏览器因弹性滚动而弹跳页面时点击“下一篇文章”,scrollTo
将无法正常工作。似乎在替换了大部分 DOM 并重置滚动位置之后,弹跳效果中的一些剩余事件“到达”并使滚动在 重置为零之后跳到下方一两个屏幕。 p>
如何强制浏览器滚动到开头并忽略剩余的弹跳事件? 这发生在 WebKit 上。
【问题讨论】:
【参考方案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。
【讨论】:
以上是关于如果在弹性滚动弹跳时更改 DOM,则滚动位置会跳转的主要内容,如果未能解决你的问题,请参考以下文章
位置:粘性 - 结合 javascript 高度调整时滚动弹跳
分组 TableView,使用自定大小的部分标题,重新加载后,如果我向上滚动,tableview 会跳转