我有一种情况,我想在 1 秒内将 600px 宽的 div 的宽度设置为 0px。为此,我可以使用 requestAnimationFrame()
。但我真的不能 100% 确定动画是否需要 1 秒。
它看起来像这样:
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 时,它会影响动画的持续时间(在 30 fps 时需要 2 秒,在 60 fps 时需要 1 秒)。我想确保动画的持续时间始终为一秒。如果 fps-rate 不同,我想根据持续时间更改宽度的新值(因此以 30 fps 设置动画我们将每步更改宽度 20 (600px/30fps))。
- 有什么方法可以在使用
requestAnimationFrame
时实现这一点?如果我能得到帧之间的平均间隔或我认为可行的 fps。 - 我是不是在担心一些并不是什么大问题的事情?
- 我在不同设备(移动设备、个人电脑、平板电脑等)上预期的 fps 是多少?
文档:https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
最佳答案
requestAnimationFrame
将页面加载后的时间传递给回调,例如
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 中的任何一个并将结果传递给 lerp,您可以更改动画与 these styles of motion 中的任何一个相匹配的方式。 .
关于你的其他问题
Is there any way I can achieve this while using requestAnimationFrame? If I could get the average interval between frames or the fps that would work I think.
您可以计算帧之间的间隔。示例:
let then = performance.now();
function animate(now) {
deltaTimeInMilliseconds = (now - then);
then = now;
...
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Am I perhaps worrying about something that isn't really a big issue?
只有你能回答这个问题
What fps can I expect on different devices (mobile, pc, tablet, etc.)?
大多数设备的帧率为 60fps,但也有以 120fps 或 240fps 运行的游戏显示器以及通常以 90fps 或更高帧率运行的 VR(和 WebVR),您可以在 VR 中使用浏览器。您是否关心其中任何一种情况取决于您。
关于javascript - 如何独立于刷新率计时 requestAnimationFrame(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46852857/