requestAnimationFrame(rAF)是实现JavaScript动画最推荐的方式,它由浏览器调度、与屏幕刷新率同步(通常60fps),比setTimeout/setInterval更高效流畅省电;其回调自动传入时间戳,需手动递归调用以实现循环动画,后台标签页会自动降频。

JavaScript 实现动画效果的核心是让元素的样式在短时间内连续、平滑地变化,而 requestAnimationFrame(简称 rAF)是现代 Web 中最推荐的方式——它由浏览器调度,与屏幕刷新率同步(通常 60fps),比 setTimeout 或 setInterval 更高效、更流畅、更省电。
requestAnimationFrame 的基本用法
rAF 接收一个回调函数作为参数,浏览器会在下一次重绘前执行该函数。它返回一个整数 ID,可用于取消动画(配合 cancelAnimationFrame)。
关键点:
- 回调函数会自动传入一个时间戳(DOMHighResTimeStamp),表示当前帧开始的时间(毫秒级,精确到微秒)
- 它不是自动循环的——想实现持续动画,需在回调内部再次调用
requestAnimationFrame - 页面处于后台标签页时,rAF 会自动降频或暂停,节省资源
写一个简单的位移动画
比如让一个 <div id="box"> 从左到右匀速移动 400px:<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/c1c2c2ed740f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Java免费学习笔记(深入)</a>”;</p>
<font size="2"><pre class='brush:php;toolbar:false;'>const box = document.getElementById('box');
let startTime = null;
const duration = 2000; // 动画总时长 2s
const startX = 0;
const endX = 400;
<p>function animate(currentTime) {
if (!startTime) startTime = currentTime;
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1); // 防止超限
const x = startX + (endX - startX) * progress;</p><p>box.style.transform = <code>translateX(${x}px)</code>;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/ai/1837" title="Mokker AI"><img
src="https://img.php.cn/upload/ai_manual/000/969/633/68b6c9b25e117919.png" alt="Mokker AI" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/ai/1837" title="Mokker AI">Mokker AI</a>
<p>AI产品图添加背景</p>
</div>
<a href="/ai/1837" title="Mokker AI" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p>if (progress < 1) {
requestAnimationFrame(animate);
}
}</p><p>requestAnimationFrame(animate);
</pre></font><h3>封装可复用的动画函数</h3>
<p>为避免每次手写时间计算,可以封装一个简易的 <code>animate 工具函数:
支持:起始值、目标值、缓动函数、完成回调
function animate({ from, to, duration = 300, easing = t => t, onUpdate, onComplete }) {
const start = performance.now();
function step(current) {
const elapsed = current - start;
const progress = Math.min(elapsed / duration, 1);
const value = from + (to - from) * easing(progress);
<pre class="brush:php;toolbar:false;">onUpdate(value);
if (progress < 1) {
requestAnimationFrame(step);
} else if (onComplete) {
onComplete();
}} requestAnimationFrame(step); }
// 使用示例:给 opacity 做淡入 animate({ from: 0, to: 1, duration: 800, easing: t => t * t, // 缓入 onUpdate: val => box.style.opacity = val, onComplete: () => console.log('动画完成') });
和 CSS 动画/transition 的区别与选择
rAF 适合需要 JavaScript 动态控制的场景,例如:
- 跟随鼠标或滚动实时响应的动画(如视差、拖拽反馈)
- 复杂物理模拟(弹簧、碰撞、惯性滚动)
- 需要逐帧读取/修改多个元素状态的动画序列
而纯展示型、声明式的动画(如按钮悬停、页面切换),优先使用 CSS transition 或 @keyframes——它们由 GPU 加速,性能更好,代码更简洁,且天然支持硬件加速和系统偏好(如减少动画)。









