如何运行 一个requestAnimationFrame 动画持续一段时间?
How to run a requestAnimationFrame animation for a certain duration?
我有以下功能,通过每次“滴答”调整它们的样式,将一些元素“向上”滚动到视图之外:
const incr = 1;
let moved = 0;
function changeHeight( children, duration, setTop) {
// duration = 1500
const height = children.clientHeight; // in this case, 166px
let moved = 0;
const slideUp = function (timestamp) {
// we're done if the amount moved is larger than height
if ( moved < height ) {
children.style.top = `${ setTop( moved, height ) }px`;
moved = moved + incr // move by some amount
requestAnimationFrame(slideUp)
} else {
// reset
moved = 0;
}
};
// start sliding
slideUp();
}
如果 requestAnimationFrame
大约每 16 毫秒左右触发一次,我想使用 duration
来指定动画 运行 的时长,因此公式似乎是 height * 16.5 / duration
我对 requestAnimationFrame
感到困惑 - 为什么每个滴答的时间不是恒定的?我想使用由 requestAnimationFrame
生成的 timestamp
但前几个周期比 ~16.5
的平均值长 很多
16.5 在不同的机器或屏幕上看起来会有所不同吗?
如何使高度变化恰好在指定的时间内完成?
你想要的叫做增量时间。
公式为Math.min((now - start) / duration, 1) * final_amount
.
使用这个增量时间,你不需要关心你的间隔触发的频率,每一步都呈现在“它应该在的地方”。
关于你的问题,
why is the time per tick not constant
当然是因为浏览器在第一帧有很多事情要做,不能在 16.7 毫秒的帧内完成所有事情。因此,它会将您的回调移到稍后执行,如果压力太大,甚至可能会跳帧。
Is the 16.5 going to look different on a different machine or screen?
是的,requestAnimationFrame
基本上会尝试跟随显示器的刷新率。所以在 60Hz 的显示器上你确实每帧有 16.7ms,但在 120Hz 的显示器上你只有一半。
How do I make the height change take exactly the amount of time specified?
使用增量时间:
const elem = document.querySelector("div");
let moved = 0;
changeHeight(elem, 200, 5000);
function changeHeight(elem, height, duration) {
const start = performance.now();
const step = function () {
const now = performance.now();
const delta = Math.min((now - start) / duration, 1);
elem.style.height = (delta * height) + "px";
if (delta < 1) {
requestAnimationFrame(step);
}
};
step();
}
div { width: 50px; background: green; }
<div></div>
我有以下功能,通过每次“滴答”调整它们的样式,将一些元素“向上”滚动到视图之外:
const incr = 1;
let moved = 0;
function changeHeight( children, duration, setTop) {
// duration = 1500
const height = children.clientHeight; // in this case, 166px
let moved = 0;
const slideUp = function (timestamp) {
// we're done if the amount moved is larger than height
if ( moved < height ) {
children.style.top = `${ setTop( moved, height ) }px`;
moved = moved + incr // move by some amount
requestAnimationFrame(slideUp)
} else {
// reset
moved = 0;
}
};
// start sliding
slideUp();
}
如果 requestAnimationFrame
大约每 16 毫秒左右触发一次,我想使用 duration
来指定动画 运行 的时长,因此公式似乎是 height * 16.5 / duration
我对 requestAnimationFrame
感到困惑 - 为什么每个滴答的时间不是恒定的?我想使用由 requestAnimationFrame
生成的 timestamp
但前几个周期比 ~16.5
16.5 在不同的机器或屏幕上看起来会有所不同吗?
如何使高度变化恰好在指定的时间内完成?
你想要的叫做增量时间。
公式为Math.min((now - start) / duration, 1) * final_amount
.
使用这个增量时间,你不需要关心你的间隔触发的频率,每一步都呈现在“它应该在的地方”。
关于你的问题,
why is the time per tick not constant
当然是因为浏览器在第一帧有很多事情要做,不能在 16.7 毫秒的帧内完成所有事情。因此,它会将您的回调移到稍后执行,如果压力太大,甚至可能会跳帧。
Is the 16.5 going to look different on a different machine or screen?
是的,requestAnimationFrame
基本上会尝试跟随显示器的刷新率。所以在 60Hz 的显示器上你确实每帧有 16.7ms,但在 120Hz 的显示器上你只有一半。
How do I make the height change take exactly the amount of time specified?
使用增量时间:
const elem = document.querySelector("div");
let moved = 0;
changeHeight(elem, 200, 5000);
function changeHeight(elem, height, duration) {
const start = performance.now();
const step = function () {
const now = performance.now();
const delta = Math.min((now - start) / duration, 1);
elem.style.height = (delta * height) + "px";
if (delta < 1) {
requestAnimationFrame(step);
}
};
step();
}
div { width: 50px; background: green; }
<div></div>