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

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

前端开发时,流畅的动画效果很重要,能明显提升用户体验。但实现动画的方法有很多,到底该选哪种呢?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

纯CSS3实现各种表情动画

CSS3非常强大,我们可以利用CSS3相关特性绘制很多平面图形,并且可以制作很多简单的动画。今天要分享的是一款用纯CSS3实现的可爱表情动画

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

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

新手引导动画的4种实现方式

尽量多的列举出新手引导动画的实现方式, 昨天稍微总结了一下, 实现了4种.源码在最后,如果想直接看结果的,可以拉到最后去看.这里假设所有的弹出层都是基于页面上原有的元素

为何 Canvas 内元素动画总是在颤抖?

在项目中我们可能对动画进行锁帧,帧率可能是 60 或者 30,如果我们想保证渲染不抖动,在匀速直线运动中,我们尽量保证我们设置的速度要是帧率的倍数,或者保证平均每帧移动的像素点是一样的

前端开发常用css动画代码

常用的CSS动画效果,在实际开发中经常需要用到移动、大小、闪烁、渐显、渐隐等动画效果,这篇文章就整理了些常见的动画效果分享给大家,一遍收藏使用。

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

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

css transition 实现滑入滑出

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

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

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

超酷的CSS3 loading预加载动画特效

这是一款超酷CSS3 loading预加载动画特效。该loading特效共有4种不同的效果,分别通过不同的CSS3 keyframes帧动画来完成。HTML结构:4种loading预加载动画的HTML结构分别如下

Vue 动画的封装

js提供的钩子动画before-enter、enter、after-enter,用这种方法写,所有的动画都写在了组件里,外部只需要调用这个fade组件就可以了,也不需要全局去写一些样式了,这种动画的封装是比较推荐的一种动画封装,因为它可以把所有动画的实现完整的封装在一个组件中

点击更多...

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