每次用户滚动到某个部分时,我都会尝试更新页面哈希:
<section data-anchor="projects"></section>
$(document).bind('scroll',function(e){
$('section').each(function(){
var element = $(this),
dataHashValue = element.data('anchor');
if(dataHashValue) {
var sectionOffset = 10,
elementOffsetTop = element.offset().top,
elementHeight = element.height(),
currentPageOffsetY = window.pageYOffset;
if (elementOffsetTop < currentPageOffsetY + sectionOffset
&& elementOffsetTop + elementHeight > currentPageOffsetY + sectionOffset) {
window.location.hash = dataHashValue;
}
}
});
});
我的问题是我遇到了性能问题,当用户快速滚动时,帧速率会下降很多......如何优化此代码? (我尝试了历史API,但这让事情变得更糟)。
编辑:按照Taytorious的建议,我实现了一个Debouncer,但更新功能中的循环仍在大幅降低我的帧率function AutoHash() {
this.scroller = window;
this.elements = $('[data-anchor]').map(function(index, item) {
var $element = $(item);
return {
yOffset: $element.offset().top,
height: $element.height(),
dataHashValue: $element.data('anchor')
};
});
}
update : function (lastScroll, currentScroll) {
this.elements.each(function(index, item) {
var sectionOffset = 10,
currentPageOffsetY = currentScroll;
if (item.yOffset < currentPageOffsetY + sectionOffset
&& item.yOffset + item.height > currentPageOffsetY + sectionOffset) {
window.location.hash = item.dataHashValue;
}
});
}
答案 0 :(得分:1)
您可以使用这样的智能滚动:)
var smartScroll;
$(window).scroll(function(){
clearTimeout(smartScroll);
smartScroll = setTimeout(doneScrolling, 100);
});
function doneScrolling(){
console.log('Your performance scrollcode here');
}
它的作用是在滚动停止后运行100ms。您甚至可以将ms降低到您认为适合性能的范围。也许20ms也会。
更准确地说,如果用户继续在ms限制内滚动,它会终止donescrolling功能。但是当用户停止滚动时,它不会终止完成滚动功能的最后一次设置超时调用。
和平与爱!答案 1 :(得分:1)
问题是浏览器每秒多次触发滚动事件(因浏览器而异)。您正在迭代循环并操纵DOM,这些是快速连续执行的昂贵操作。你可以通过滚动debouncer和一点代码重构来解决这个问题。对于滚动去抖动:
function scrollDebounce(context, callback) {
var latestKnownScrollY = 0,
lastScroll = 0;
ticking = false;
function onScroll() {
latestKnownScrollY = window.scrollY;
requestTick();
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(update);
}
ticking = true;
}
function update() {
// reset the tick so we can
// capture the next onScroll
ticking = false;
var currentScrollY = latestKnownScrollY;
callback.apply(context, [lastScroll, currentScrollY]);
lastScroll = currentScrollY;
}
$(window).scroll(onScroll);
}
仅当浏览器请求新帧时才会执行回调。对于回调,您可能不希望每次都遍历所有部分。我将所有部分的偏移位置存储在某种数据结构中,并跟踪当前部分。这样,您可以轻松地迭代到下一个/上一个部分,具体取决于用户是向上还是向下滚动。
this.currentIndex = 0;
function AutoHash() {
this.scroller = window;
this.elements = $('[data-anchor]').map(function(index, item) {
var $element = $(item);
return {
top: $element.offset().top,
bottom: $element.offset().top + $element.height(),
dataHashValue: $element.data('anchor')
};
});
}
update : function (lastScroll, currentScroll) {
if (lastScroll < currentScroll && this.elements[this.currentIndex + 1].top < currentScroll) {
this.currentIndex++;
} else if (lastScroll > currentScroll && this.elements[this.currentIndex - 1].bottom > currentScroll && this.currentIndex > 0) {
this.currentIndex--;
}
window.location.hash = this.elements[this.currentIndex].dataHashValue;
}
scrollDebounce(this, this.update);