Web API中的requestAnimationFrame
视觉暂留
首先要学习requestAnimationFrame就需要先了解一个概念叫做视觉暂留
视觉暂留是人眼观看景物或影像时,当光信号突然消失时,大脑中的视觉形象会暂时保留约0.1秒的生理现象,也就是我们平时看到的动画,就是一帧一帧的,通过高速的切换,中间的停顿时间由于视觉暂留补齐了
原理
requestAnimationFrame是浏览器刷新同步的动画利器,是一个浏览器原生的API,它将指定的函数注册到浏览器的刷新队列中。
浏览器通常以每秒60帧(FPS)的速度刷新,因此requestAnimation会在每一帧渲染前执行注册的函数,确保动画与浏览器的刷新机制完美同步
requestAnimationFrame 的用法
requestAnimationFrame(回调函数)
功能:将回调函数,延迟到下一帧(下一次网页重绘)前执行。
在回调函数内再次调用 requestAnimationFrame()
requestAnimationFrame(function update() {
console.log("执行了更新!");
// requestAnimationFrame 的回调函数默认只会被调用一次,如果希望每帧都执行,则每帧都需要调用
requestAnimationFrame(update);
});
取消执行
requestAnimationFrame(回调函数)
会返回一个整数(定时器的编号),将其传给cancelAnimationFrame(定时器的编号)
可取消回调函数的执行,如:
// 定义定时器
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),需在代码前添加以下兼容代码:
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;
}
}