2017-10-20 100 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();