2016-05-17 54 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功能。但是,当用户停止滚动时,它不会终止完成的滚动功能的最后一次设置的超时调用。

和平与爱!