2016-08-14 45 views
0

在我的網站上,一個相關的內容框應該在視口可見時進行動畫處理。60fps:如何正確使用requestAnimationFrame?

我試圖通過CSS和JavaScript使我的動畫儘可能高效,這樣它就不會負面影響滾動性能。

儘管CSS部分很簡單(使用transform,will-change,contains),但我在使用window.requestAnimationFrame時掙扎了一下。

只有當類添加到元素中時,或者在函數isScrolledIntoView被調用時,或者甚至在isScrolledIntoView中,何時測量元素位置,我才應該使用它嗎?

var percentVisible = 0.25; 
window.addEventListener('scroll', function(){ 
relatedContent(related, percentVisible); 
} 
) 

function relatedContent(r, pV){ 
    window.requestAnimationFrame(function() { 
     if(isScrolledIntoView(r, pV)){ 
      window.requestAnimationFrame(function(){ 
       r.classList.add("visible"); 
      }, r) 
     } 
    }, r) 
} 

function isScrolledIntoView(el, percentV) { 
var elemTop, elemBottom, elemHeight, overhang, isVisible; 
/*window.requestAnimationFrame(
function(){*/ 
elemTop = el.getBoundingClientRect().top; 
elemBottom = el.getBoundingClientRect().bottom; 
elemHeight = el.getBoundingClientRect().height; 
/*} 
);*/ 
overhang = elemHeight * (1 - percentV); 

isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang); 
return isVisible; 
} 

回答

1

沒有不使用它,這樣的...

  • requestAnimationFrame(RAF)是不與屏幕刷新率(通常60fps的)同步計時功能。
  • 滾動事件每秒可能觸發的事件超過60次。
  • 每次調用rAF都會將所有作爲其參數傳遞給它的函數都堆疊在某種在下一次屏幕刷新之前調用的大函數中。

結合所有這一切,你得到的是多次調用堆棧中的同一個函數,就在下一次屏幕刷新之前。

相反,你似乎想要的是防止你的滾動事件發生時沒有用。這就是所謂的油門功能,你有點遠離它。

這裏是英國皇家空軍使用一個簡單的油門實現:

var throttle = function(callback) { 
    var active = false; // a simple flag 
    var evt; // to keep track of the last event 
    var handler = function(){ // fired only when screen has refreshed 
    active = false; // release our flag 
    callback(evt); 
    } 
    return function handleEvent(e) { // the actual event handler 
    evt = e; // save our event at each call 
    if (!active) { // only if we weren't already doing it 
     active = true; // raise the flag 
     requestAnimationFrame(handler); // wait for next screen refresh 
    }; 
    } 
} 

,你可以使用這樣的:

window.addEventListener('scroll', throttle(yourScrollCallback));