js中requestAnimationFrame()解读与使用示例

 更新时间:2024年09月12日 09:33:18   作者:OEC小胖胖  
requestAnimationFrame()是JavaScript中用于创建高效、流畅动画的核心方法,它与浏览器的重绘过程同步,确保每次动画更新都与显示器刷新率同步,下面就来一起了解一下

requestAnimationFrame() 是 JavaScript 中用于实现动画效果的一个重要方法。它告诉浏览器你想执行动画,并要求浏览器在下次重绘之前调用指定的回调函数来更新动画。相比传统的 setTimeout 和 setIntervalrequestAnimationFrame() 更加高效且能够提供更流畅的动画。

基本概念

1. 浏览器的重绘和回流

浏览器通过一个叫做“帧”的机制来渲染页面内容。一般来说,浏览器每秒会尝试绘制 60 帧(60FPS),每一帧都需要浏览器计算布局、样式,并把内容绘制到屏幕上。requestAnimationFrame() 是专门为此设计的,它会让你的动画代码在浏览器的重绘过程中执行,确保每次动画更新都与浏览器的刷新频率同步。

2. 效率和节能

requestAnimationFrame() 会根据显示器的刷新率来自动调节帧率,常见的刷新率是 60FPS。如果你的显示器是 60Hz,requestAnimationFrame() 每秒会回调约 60 次。如果浏览器窗口被最小化,或者切换到另一个标签页,requestAnimationFrame() 会暂停执行,减少CPU和GPU的负载。这和 setTimeoutsetInterval 不同,它们会一直执行,即使页面不可见。

使用方法

let start = null;

function step(timestamp) {
  if (!start) start = timestamp;
  const progress = timestamp - start;

  // 更新动画的位置,这里是简单的例子,假设移动一个物体
  const element = document.getElementById('box');
  element.style.transform = `translateX(${Math.min(progress / 10, 200)}px)`;

  if (progress < 2000) { // 继续动画,直到经过2秒
    requestAnimationFrame(step);
  }
}

requestAnimationFrame(step);

示例详解

1. 回调函数

requestAnimationFrame() 需要一个回调函数作为参数,这个回调函数会在浏览器准备好绘制下一帧时被调用。在上面的示例中,step 函数就是这个回调函数。

2. timestamp 参数

浏览器会为回调函数传递一个 timestamp 参数,表示当前被请求的动画帧开始时的时间戳。这个 timestamp 是以毫秒为单位的高精度时间,可以用来计算动画进行的时间差。

3. 递归调用

在 step 函数内部,我们通过 requestAnimationFrame() 自己调用自己,形成一个动画的递归循环。每一次调用 requestAnimationFrame(step),浏览器都会在下一帧时再次执行 step 函数。

4. 条件控制

为了停止动画,我们可以在递归调用时通过条件判断,比如在上面的例子中,我们通过 progress < 2000 来控制动画持续 2 秒。如果不加这个条件,动画会一直进行下去。

与 setTimeout 和 setInterval 的比较

function moveBoxWithSetTimeout() {
  let position = 0;
  const element = document.getElementById('box');

  function update() {
    position += 5;
    element.style.transform = `translateX(${position}px)`;
    
    if (position < 200) {
      setTimeout(update, 1000 / 60); // 每秒60次更新
    }
  }

  update();
}

function moveBoxWithRequestAnimationFrame() {
  let position = 0;
  const element = document.getElementById('box');

  function update() {
    position += 5;
    element.style.transform = `translateX(${position}px)`;

    if (position < 200) {
      requestAnimationFrame(update);
    }
  }

  requestAnimationFrame(update);
}

区别:

  • 时间控制

    • setTimeout(update, 1000 / 60) 人为指定每秒60帧,但实际性能可能受限于浏览器、CPU 等,不一定精准。
    • requestAnimationFrame() 由浏览器根据系统的负载来决定最佳帧率,并与显示器的刷新同步。
  • 后台标签页处理

    • setTimeout 和 setInterval 在后台标签页或最小化时仍然运行,浪费资源。
    • requestAnimationFrame() 会在页面不可见时暂停,节省资源。
  • 流畅度

    • setTimeout 和 setInterval 由于无法和浏览器的重绘同步,容易导致卡顿、抖动。
    • requestAnimationFrame() 能提供更加平滑的动画效果。

多个动画场景

你可以通过 requestAnimationFrame() 同时控制多个动画。只需要确保每个动画逻辑在回调函数中被正确处理。

let box1 = document.getElementById('box1');
let box2 = document.getElementById('box2');
let start = null;

function animate(timestamp) {
  if (!start) start = timestamp;
  const progress = timestamp - start;

  box1.style.transform = `translateX(${Math.min(progress / 10, 200)}px)`;
  box2.style.transform = `translateY(${Math.min(progress / 20, 300)}px)`;

  if (progress < 2000) {
    requestAnimationFrame(animate);
  }
}

requestAnimationFrame(animate);

上面的代码演示了:

  • box1 向右移动,每 10 毫秒移动一个像素,直到移动 200 像素。
  • box2 向下移动,每 20 毫秒移动一个像素,直到移动 300 像素。

多个元素的动画可以在同一个 requestAnimationFrame 回调中进行,这样它们会同步进行,保证帧率的一致性。

动画的取消

requestAnimationFrame() 返回一个唯一的整数 ID,代表该动画帧请求。可以使用 cancelAnimationFrame() 取消这个动画。

let animationId;

function step(timestamp) {
  // 动画逻辑
  if (progress &lt; 2000) {
    animationId = requestAnimationFrame(step);
  }
}

// 开始动画
animationId = requestAnimationFrame(step);

// 取消动画
cancelAnimationFrame(animationId);

总结

  • 同步与浏览器刷新频率requestAnimationFrame() 是与显示器的刷新率同步的动画方法,通常会以 60FPS 执行。
  • 高效与节能:在页面不可见时,requestAnimationFrame() 会暂停执行,避免不必要的计算。
  • 流畅的动画体验:由于它与浏览器的重绘同步,能带来更加流畅的动画效果。

通过掌握 requestAnimationFrame(),你可以更轻松地创建流畅且高效的动画效果,它是现代 Web 动画开发的核心工具之一。

到此这篇关于js中requestAnimationFrame()解读与使用示例的文章就介绍到这了,更多相关js requestAnimationFrame()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于JS中match() 和 exec() 返回值和属性的测试

    关于JS中match() 和 exec() 返回值和属性的测试

    这篇文章主要介绍了关于JS中match() 和 exec() 返回值和属性的测试 的相关资料,需要的朋友可以参考下
    2016-03-03
  • 解决火狐浏览器下JS setTimeout函数不兼容失效不执行的方法

    解决火狐浏览器下JS setTimeout函数不兼容失效不执行的方法

    今天检查自己用JQuery+AJAX+PHP做的网站后台登录检测,爱其他浏览器中兼容性还不错 结果到了火狐(FireFox)浏览器下setTimeout这个JS内置函数不执行了,本文将提供详细的解决方法
    2012-11-11
  • JS实现的DIV块来回滚动效果示例

    JS实现的DIV块来回滚动效果示例

    这篇文章主要介绍了JS实现的DIV块来回滚动效果,结合实例形式分析了JS通过时间函数定时触发动态改变页面元素样式的相关操作技巧,需要的朋友可以参考下
    2017-02-02
  • JavaScript实现excel文件导入导出

    JavaScript实现excel文件导入导出

    这篇文章主要介绍了JavaScript实现excel文件导入导出,文件的导入导出是非常常见的需求功能,excel文件的导入导出更为常见,实践中许多时候,是调用接口实现导入导出的,具体实现内容需要的小伙伴可以参考一下
    2022-06-06
  • 微信小程序scroll-view实现自定义滚动条

    微信小程序scroll-view实现自定义滚动条

    这篇文章主要为大家详细介绍了微信小程序scroll-view实现自定义滚动条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 无constructor的class类还能new吗问题解析

    无constructor的class类还能new吗问题解析

    这篇文章主要为大家介绍了无constructor的class类是否还能new的问题解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 详解JavaScript常量定义

    详解JavaScript常量定义

    本文主要对JavaScript常量定义进行详细介绍,具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 详解JavaScript中8 种不同的继承实现方式

    详解JavaScript中8 种不同的继承实现方式

    在 JavaScript 中,继承是实现代码复用和构建复杂对象关系的重要机制,虽然 JavaScript 是一门基于原型的语言,不像传统面向对象语言那样有类的概念,但它提供了多种实现继承的方式,本文将详细介绍 JavaScript 中 8 种不同的继承实现方式,需要的朋友可以参考下
    2025-05-05
  • 详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑

    详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑

    这篇文章主要介绍了详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • JAVASCRIPT HashTable

    JAVASCRIPT HashTable

    JAVASCRIPT HashTable...
    2007-01-01

最新评论