2017-10-20 97 views
0

我有一種情況,我想在1秒內將600px寬的div的寬度設置爲0px。我可以使用requestAnimationFrame()。但如果動畫需要1秒鐘,我不會100%確定。如何調用requestAnimationFrame()獨立於refreshrates

這將是這個樣子:

let width = 600; 
let animation; 
function animateWidth(){ 
    if(width <= 0){ 
    window.cancelAnimationFrame(); 
    }else{ 
    width -= 10; // (600px/60fps) 
    } 
    document.getElementById('id1').setAttribute('width', width); 
    animation = window.requestAnimationFrame(animateWidth); 
} 
animation = window.requestAnimationFrame(animateWidth); 

的事情是,當一個設備有不同的FPS會影響動畫的持續時間(在30fps的有可能需要2秒和60幀它將採取一個)。我想確保這個動畫的持續時間總是一秒鐘。如果fps率不同,我想根據持續時間更改寬度的新值(所以在30 fps下動畫我們會將寬度每改變20(600px/30fps))。

  • 有沒有什麼辦法可以在使用​​時達到這個目的?如果我能得到幀之間的平均間隔或我認爲可行的fps。
  • 我是否擔心這件事不是一個大問題?
  • 在不同的設備(手機,電腦,平板電腦等)上我可以期待什麼樣的fps?

文檔:https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame

+3

你可以通過使用['performance.now()'](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)來做到這一點。 – Xufox

回答

2

​​通過以來,頁面加載回調因此,例如時間

const startValue = 600; 
 
const endValue = 0; 
 

 
// return a value between start and end as l goes from 0 to 1 
 
function lerp(start, end, l) { 
 
    return start + (end - start) * l; 
 
} 
 

 
const startTime = performance.now(); 
 
const durationInSeconds = 1; 
 
const element = document.getElementById('id1'); 
 

 
function animateWidth(now) { 
 
    const timeSinceStartInSeconds = (now - startTime) * 0.001; 
 

 
    // l goes from 0 to 1 over durationInSeconds; 
 
    const l = Math.min(timeSinceStartInSeconds/durationInSeconds, 1); 
 

 
    element.setAttribute('width', lerp(startValue, endValue, l)); 
 

 
    // if we haven't finished request another animation frame 
 
    if (l < 1) { 
 
    requestAnimationFrame(animateWidth); 
 
    } 
 
} 
 
requestAnimationFrame(animateWidth);
#id1 { background: red; }
<canvas id="id1"></canvas>

如果是我我可能會嘗試,使之成爲功能

// return a value between start and end as l goes from 0 to 1 
 
function lerp(start, end, l) { 
 
    return start + (end - start) * l; 
 
} 
 

 
function animateAttribute(element, attribute, startValue, endValue, duration) { 
 
    const startTime = performance.now(); 
 

 
    function animate(now) { 
 
    const timeSinceStart = (now - startTime) * 0.001; 
 

 
    // l goes from 0 to 1 over durationInSeconds; 
 
    const l = Math.min(timeSinceStart/duration, 1); 
 

 
    element.setAttribute(attribute, lerp(startValue, endValue, l)); 
 

 
    // if we haven't finished request another animation frame 
 
    if (l < 1) { 
 
     requestAnimationFrame(animate); 
 
    } 
 
    } 
 
    requestAnimationFrame(animate); 
 
} 
 

 
const element = document.getElementById('id1'); 
 
const attribute = 'width'; 
 
const start = 600; 
 
const end= 0; 
 
const duration = 1; 
 

 
animateAttribute(element, attribute, start, end, duration);
#id1 { background: red; }
<canvas id="id1"></canvas>

還通過傳遞l任何的these functions並傳遞結果線性插值可以更改動畫是如何發生的,以匹配任何these styles of motion

至於你的其他問題

有什麼辦法,而使用requestAnimationFrame我能做到這一點?如果我能得到幀之間的平均間隔或我認爲可行的fps。

您可以計算幀之間的間隔。例如:

let then = performance.now(); 
function animate(now) { 
    deltaTimeInMilliseconds = (now - then); 
    then = now; 

    ... 
    requestAnimationFrame(animate); 
} 
requestAnimationFrame(animate); 

上午我也許擔心的東西是不是一個真正的大問題?

只有你能回答這個問題

我可以期待在不同的設備(手機,PC,平板電腦等)FPS什麼?

大多數設備都是60fps的,但也有在120fps的或240fps的運行以及玩家顯示器VR(和WebVR)通常運行在達到90fps以上,可以使用內部VR瀏覽器。你是否在乎這些情況取決於你。

0

測量時間,因爲動畫的開始和使用它作爲在寬度計算的參考。將這裏的普遍做法。

使用此代碼無論設備具有哪種FPS,動畫都會持續一秒。

const el = document.getElementById('id1'); 
const start = Date.now(); 

function animateWidth() { 
    const t = (Date.now() - start)/1000; // 1000 - one second 

    if(t >= 1) { 
    el.setAttribute('width', 0); 
    } 
    else { 
    el.setAttribute('width', 600 * (1 - t)); 
    window.requestAnimationFrame(animateWidth); 
    } 
} 

animateWidth();