前端动画选哪个更好:requestAnimationFrame vs 定时器

更新日期: 2025-10-29 阅读: 297 标签: 动画

前端开发时,流畅的动画效果很重要,能明显提升用户体验。但实现动画的方法有很多,到底该选哪种呢?requestAnimationFrame 和定时器(setTimeout、setInterval)都是常用的动画实现方法,它们在工作原理、性能表现和使用场景上都有很大不同。


requestAnimationFrame 是什么?

这是浏览器专门为动画提供的接口。它告诉浏览器在下次页面重绘前执行你的动画代码

基本用法很简单:

let requestId = requestAnimationFrame(callback);
  • callback:浏览器在下次重绘前调用的函数

  • requestId:请求的标识号,可以用来取消动画

工作原理

浏览器运行时有个事件循环机制,处理各种任务。requestAnimationFrame 的回调函数会被放到浏览器的动画帧队列里,在重绘阶段执行。简单说,浏览器每次要更新画面时,会先执行这些动画函数,然后再绘制页面。

优点

  1. 与浏览器刷新同步:动画更新和页面重绘保持同步,避免不必要的重复绘制,性能更好

  2. 智能节能:当页面被隐藏或切到后台时,浏览器会自动暂停动画,节省资源

  3. 动画更流畅:帧率与浏览器刷新率匹配,通常是每秒60帧,动画效果很顺滑

缺点

  1. 兼容性问题:老版本浏览器可能不支持,需要做兼容处理

  2. 不能控制执行频率:执行间隔由浏览器决定,不能像定时器那样精确设置


定时器是什么?

主要通过 setTimeout 和 setInterval 来实现:

  • setTimeout:延迟指定时间后执行一次代码

let timeoutId = setTimeout(function, delay);
  • setInterval:按固定时间间隔重复执行代码

let intervalId = setInterval(function, delay);

工作原理

定时器在设定的时间后把回调函数放入执行队列,等待处理。但由于JavaScript是单线程的,如果当前有任务在执行,定时器的回调可能要等更久才能运行。

优点

  1. 简单好用:用法直观,容易理解

  2. 能控制频率:可以精确设置执行间隔,适合需要固定频率的场景

缺点

  1. 性能问题:如果回调函数执行太久,会阻塞后面代码,影响页面响应

  2. 时间不准:实际执行间隔可能比设定的长,导致动画卡顿

  3. 不会自动优化:即使页面看不见,定时器也会继续执行,浪费资源


两者对比

性能方面

requestAnimationFrame更好,它与浏览器重绘同步,动画流畅,而且在页面不可见时会自动暂停。

定时器可能因为JavaScript执行阻塞导致时间不准,影响动画效果,也没有优化机制。

适用场景

requestAnimationFrame:适合大多数动画场景,特别是需要流畅动画的地方,比如游戏、复杂交互动画。

定时器:适合简单的、对流畅度要求不高的动画,或者需要精确时间控制的非动画任务,比如定期请求数据、倒计时功能。

代码示例对比

用 requestAnimationFrame 实现动画:

let startTime = null;
const element = document.getElementById('box');

function animate(currentTime) {
  if (!startTime) startTime = currentTime;
  const elapsed = currentTime - startTime;
  
  // 假设动画持续2秒
  const progress = Math.min(elapsed / 2000, 1);
  
  element.style.transform = `translateX(${progress * 200}px)`;
  
  if (progress < 1) {
    requestAnimationFrame(animate);
  }
}

requestAnimationFrame(animate);

用 setInterval 实现动画:

const element = document.getElementById('box');
const startTime = Date.now();
const duration = 2000; // 动画持续2秒

const intervalId = setInterval(() => {
  const elapsed = Date.now() - startTime;
  const progress = Math.min(elapsed / duration, 1);
  
  element.style.transform = `translateX(${progress * 200}px)`;
  
  if (progress >= 1) {
    clearInterval(intervalId);
  }
}, 16); // 大约每秒60帧

requestAnimationFrame 的动画更流畅,而且有浏览器优化。setInterval 的动画可能会卡顿。


实际使用建议

  1. 优先选择 requestAnimationFrame
    做动画时首先考虑用它,性能和流畅度都更好。

  2. 处理兼容性问题
    对于不支持 requestAnimationFrame 的老浏览器,可以这样降级:

    window.requestAnimationFrame = window.requestAnimationFrame || 
                                 window.webkitRequestAnimationFrame || 
                                 window.mozRequestAnimationFrame || 
                                 function(callback) {
                                     return setTimeout(callback, 1000 / 60);
                                 };
  3. 避免在动画回调中做复杂操作
    不管是 requestAnimationFrame 还是定时器,在回调函数里都不要做太复杂的计算或dom操作,否则会影响动画性能。

  4. 及时清理动画
    动画不需要时要用 cancelAnimationFrame 或 clearInterval 及时停止:

    // 对于 requestAnimationFrame
    cancelAnimationFrame(requestId);
    
    // 对于 setInterval
    clearInterval(intervalId);
  5. 控制动画频率
    如果不需要60帧的高频率,可以这样控制:

    let lastTime = 0;
    const fps = 30; // 每秒30帧
    
    function animate(currentTime) {
        if (currentTime - lastTime > 1000 / fps) {
            // 执行动画逻辑
            lastTime = currentTime;
        }
        requestAnimationFrame(animate);
    }


特殊场景考虑

游戏开发
复杂游戏通常用 requestAnimationFrame,但要注意:

  • 不同显示器刷新率可能不同

  • 需要处理帧率波动

  • 可以考虑使用固定时间步长

简单UI动画
比如淡入淡出、滑动效果,直接用 css 动画可能更简单,性能也更好。

后台任务
如果是数据同步、定期检查等非动画任务,用 setInterval 更合适。

性能监控
可以监控动画性能,发现问题:

let frameCount = 0;
let lastTime = performance.now();

function checkFPS(currentTime) {
    frameCount++;
    if (currentTime - lastTime >= 1000) {
        console.log('当前FPS:', frameCount);
        frameCount = 0;
        lastTime = currentTime;
    }
    requestAnimationFrame(checkFPS);
}
requestAnimationFrame(checkFPS);


总结

requestAnimationFrame 在大多数动画场景下表现更好,是现代前端动画的首选。但定时器在特定情况下仍然有用。

选择时要考虑:

  • 动画复杂度

  • 性能要求

  • 浏览器兼容性

  • 开发成本

理解两者的区别,能帮你做出合适的选择,做出既好看又流畅的动画效果。记住,好的动画不仅要效果漂亮,还要性能优秀,不给用户设备造成负担。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/13085

相关推荐

css transition 实现滑入滑出

transition是css最简单的动画。 通常当一个div属性变化时,我们会立即看的变化,从旧样式到新样式是一瞬间的,嗖嗖嗖!!!但是,如果我希望是慢慢的从一种状态,转变成另外一种状态,怎么办? transition可以做到。

css3贝塞尔曲线(cubic-bezier)

css3 animation模块,其中animation-timing-function 和 transition-timing-function两个属性来控制动画速度分别提供了ease,liner,ease-in,ease-out

CSS动画@keyframes的用法

CSS动画允许大多数HTML元素的动画,而无需使用JavaScript或Flash!IE10+支持该属性的。其他低浏览器版本数字后跟-ms-, -webkit-,-moz-或-o-指定使用前缀的第一个版本。

css @keyframes属性 语法

@keyframes是CSS的一种规则,可以用来定义CSS动画的一个周期的行为,创建简单的动画。作用:通过 @keyframes 规则,您能够创建动画。

css3实现椭圆轨迹旋转

X轴Y轴在一个矩形内移动;设置动画延时设置Y轴延时为动画时长的一半, 运动轨迹变成菱形;设置三次贝塞尔曲线,为了看起来有立体感添加scale属性,scale动画应该是X轴和Y轴的时间总和

css环形滚动_内容加载的环形滚动动画效果

创建一个没有背景的圆,然后声明透明度为0.1的黑色边框(看起来是灰色),修改左侧边框颜色。此时会有一个静态的看起来只有左边框有颜色的空心圆。然后声明一个该元素逆时针旋转360度的动画,并让该动画无限播放(infinite)即可

Vue.js动画笔记_vue实现动画效果

Vue.js中的元素动画或页面跳转动画有多种实现方式比如:1、自己手动写CSS3动画来实现2、使用第三方CSS动画库如:Animate.css3、在构子函数中操作DOM4、使用第三方Js动画库如:Velocity.js。

动画函数的绘制及自定义动画函数

制作动画效果离不开动画运动函数,而我们用得最多的无疑就是Tween.js。根据不同的数学公式原理,Tween.js划分出了不同的动画类型,每种动画类型里面都包含以下的缓动类型:ease in 先慢后快、ease out 先块后慢、ease in out 先慢后快再慢

只用 CSS 就能做到的像素画/像素动画

这篇文章将会介绍只用 CSS 就能制作像素画·像素动画的方法。虽说纯 CSS 就能做到,但是为了更高的可维护性,也会顺便介绍使用 Sass 的制作方法。

css3 过渡和动画

在没有过渡属性的时候,当一个元素的属性值发生变化时,浏览器就会将个这个元素瞬间渲染成新属性值的样式。例如一个定位元素top:0,动态修改成top:100px,这个元素就瞬间跑到100px的位置,有时候我们为了达到某种视觉效果

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!