Web API中的requestAnimationFrame

视觉暂留

首先要学习requestAnimationFrame就需要先了解一个概念叫做视觉暂留

视觉暂留是人眼观看景物或影像时当光信号突然消失时大脑中的视觉形象会暂时保留约0 .1秒的生理现象,也就是我们平时看到的动画,就是一帧一帧的,通过高速的切换,中间的停顿时间由于视觉暂留补齐了

原理

requestAnimationFrame是浏览器刷新同步的动画利器,是一个浏览器原生的API,它将指定的函数注册到浏览器的刷新队列中。

浏览器通常以每秒60帧(FPS)的速度刷新,因此requestAnimation会在每一帧渲染前执行注册的函数,确保动画与浏览器的刷新机制完美同步

requestAnimationFrame 的用法

延迟到下一帧执行

javascript 复制代码
requestAnimationFrame(回调函数)

功能:将回调函数,延迟到下一帧(下一次网页重绘)前执行。

每一帧都执行

在回调函数内再次调用 requestAnimationFrame()

javascript 复制代码
requestAnimationFrame(function update() {
  console.log("执行了更新!");
  // requestAnimationFrame 的回调函数默认只会被调用一次,如果希望每帧都执行,则每帧都需要调用
  requestAnimationFrame(update);
});

取消执行

requestAnimationFrame(回调函数) 会返回一个整数(定时器的编号),将其传给cancelAnimationFrame(定时器的编号) 可取消回调函数的执行,如:

javascript 复制代码
// 定义定时器
let timer1 = requestAnimationFrame(回调函数)
// 取消定时器
cancelAnimationFrame(timer1)

requestAnimation与setTimeout

requestAnimationFrame 与延时执行函数 setTimeout 类似,但不用设置时间,即可将操作延迟至下一次网页重绘时执行

提升 web 性能

使用 requestAnimationFrame 替换 setTimeout 和 setInterva 可提升web性能。

setTimeout 和 setInterva 实现动画的缺点
  • 时间不精确,通常实际执行时间都要比其设定的时间晚一些。
  • 实现的动画在某些低端机上会出现卡顿、抖动的现象。(不同设备的屏幕刷新频率不同,而 setTimeout 和 setInterva 只能设置一个固定的时间间隔,这个时间和屏幕的刷新时间不同时,就会出现掉帧,而导致页面卡顿、抖动)
requestAnimationFrame 实现动画的优势

requestAnimationFrame 采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

requestAnimation与CSS动画

为什么在CSS中我们已经学习了animation,Web API中还出现了一个requestAnimationFrame

requestAnimationFrame(简称 rAF)和 CSS 动画(@keyframes)在实现动画效果时各有优劣。

性能优化

requestAnimationFrame:

同步渲染: rAF 会在浏览器的下一个重绘周期之前调用回调函数,确保动画与浏览器的刷新率同步。这意味着动画帧率可以达到 60fps(每秒 60 帧),这是大多数显示器的刷新率。

自动优化: 浏览器可以智能地优化 `rAF` 的调用,例如在标签页不可见或设备处于省电模式时暂停动画,从而节省资源。

CSS 动画:

硬件加速: CSS 动画通常会利用 GPU 加速,特别是在使用 transform 和 opacity属性时。这可以显著提高性能,尤其是在复杂的动画中。

声明式: CSS 动画是声明式的,浏览器可以更好地优化这些动画,例如通过分层和合成。

灵活性和控制

requestAnimationFrame:

细粒度控: rAF提供了更细粒度的控制,可以在每一帧中精确地调整动画状态。这对于复杂的交互和动态变化的动画非常有用。

动态调整: 可以在动画过程中动态调整动画参数,例如速度、方向、路径等。

CSS 动画:

预定义: CSS 动画是预定义的,一旦开始,很难在运行时动态调整动画参数。虽然可以通过 JavaScript 修改 CSS 动画的某些属性,但不如 `rAF` 灵活。

简单易用: 对于简单的动画效果,CSS 动画非常容易实现,不需要编写复杂的 JavaScript 代码。

兼容性和可维护性

requestAnimationFrame:

兼容性: rAF在现代浏览器中广泛支持,但在一些老旧浏览器中可能需要 polyfill。

可维护性: 由于 rAF`是基于 JavaScript 的,可以更容易地与其他 JavaScript 代码集成,维护起来也相对容易。

CSS 动画:

兼容性: CSS 动画在现代浏览器中也广泛支持,但一些老旧浏览器可能需要前缀或替代方案。

可维护性: CSS 动画的声明式特性使得代码更简洁,但对于复杂的动画逻辑,维护起来可能会有些困难。

应用场景

requestAnimationFrame:

复杂动画: 适用于复杂的交互式动画,特别是那些需要实时响应用户输入或动态调整的动画。

游戏开发: 在游戏开发中,`rAF` 是常用的动画技术,因为它提供了更高的帧率和更好的控制。

CSS 动画:

简单动画: 适用于简单的过渡和动画效果,特别是那些只需要预定义路径和时间的动画。

性能敏感: 在需要高性能且动画效果较为简单的场景中,CSS 动画是更好的选择,因为它们可以利用硬件加速。

总结

requestAnimationFrame 适合需要高精度控制和动态调整的复杂动画。

CSS 动画适合简单的、预定义的动画效果,特别是那些需要高性能且不需要频繁调整的场景。

例如,可以使用 rAF处理复杂的交互逻辑,而使用 CSS 动画处理简单的视觉效果。

requestAnimationFrame 的缺点

  • requestAnimationFrame 存在兼容性问题,在不支持的浏览器(如 IE9),需添加兼容代码
  • requestAnimationFrame 使用的主线程,若主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。

兼容写法

对不支持 requestAnimationFrame 的浏览器(如 IE9),需在代码前添加以下兼容代码:

javascript 复制代码
if(!window.requestAnimationFrame){
    var lastTime = 0;
    window.requestAnimationFrame = function(callback){
        var currTime = new Date().getTime();
        var timeToCall = Math.max(0,16.7-(currTime - lastTime));
        var id  = window.setTimeout(function(){
            callback(currTime + timeToCall);
        },timeToCall);
        lastTime = currTime + timeToCall;
        return id;
    }
}
相关推荐
NoneCoder4 分钟前
CSS系列(29)-- Scroll Snap详解
前端·css
无言非影8 分钟前
vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)
前端·css
我曾经是个程序员34 分钟前
鸿蒙学习记录
开发语言·前端·javascript
羊小猪~~1 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
摸鱼了1 小时前
🚀 从零开始搭建 Vue 3+Vite+TypeScript+Pinia+Vue Router+SCSS+StyleLint+CommitLint+...项目
前端·vue.js
程序员shen1616111 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
Ling_suu2 小时前
SpringBoot3——Web开发
java·服务器·前端
Yvemil72 小时前
《开启微服务之旅:Spring Boot Web开发》(二)
前端·spring boot·微服务
hanglove_lucky2 小时前
本地摄像头视频流在html中打开
前端·后端·html
维李设论2 小时前
Node.js的Web服务在Nacos中的实践
前端·spring cloud·微服务·eureka·nacos·node.js·express