2016-05-17 92 views
0

我想每次更新頁面顯示亂碼用戶滾動到某一部分:更新頁面顯示亂碼

<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意見,我實現了一個反跳,但是更新功能內環路仍有下探我幀率很多

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; 
      } 
     }); 
    } 

回答

1

問題是瀏覽器每秒觸發多次滾動事件(它因瀏覽器而異)。您正在遍歷一個循環並操作DOM,而這些代價很高的操作可以快速連續執行。你可以用滾動去抖器和一些代碼重構來解決這個問題。對於滾動去抖器:

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); 
+0

這很好,它有幫助,但仍有很多開銷;我將偏移量存儲在一個數組中,但是我無法想到如何在不更新每個更新時遍歷數組的情況下跟蹤當前部分,我認爲主要問題是該循環,您可以詳細闡述一下? –

+0

像這樣的東西應該工作。如果你正在尋找更清潔/更簡單的東西,請查看[航點](http://imakewebthings.com/waypoints/)。 – Taytorious

1

您可以使用智能滾動像這樣:)

var smartScroll; 

$(window).scroll(function(){ 
    clearTimeout(smartScroll); 
    smartScroll = setTimeout(doneScrolling, 100); 
}); 

function doneScrolling(){ 
    console.log('Your performance scrollcode here'); 
} 

它的功能是在滾動停止後運行100毫秒。你甚至可以將ms降低到你認爲合適的表現。也許20ms也會。

更確切地說,如果用戶在該ms限制內保持滾動,則會殺死donescrolling功能。但是,當用戶停止滾動時,它不會終止完成的滾動功能的最後一次設置的超時調用。

和平與愛!