前言:
之前没有看到过这个requestAnimationFrame,接触它源自一道选择题,如下:
答案虽然勉强蒙对了,但是关于这个函数的知识我也是一头雾水,然后专门去学习了一下requestAnimationFrame,下面且听我娓娓道来。
一、什么是requestAnimationFrame
1.1计时器与屏幕刷新率
计时器
计时器一直是javascript动画的核心技术。而编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化
屏幕刷新率
屏幕的刷新频率可在电脑中“高级显示设置”中查看,一般为60Hz,就是说,屏幕静置情况下,显示器会以每秒60次的频率不断更新屏幕上的图像,因为人的“视觉停留效应”,并感觉不到变化或者抖动,看到的仍是一幅幅连续的画面,其实这中间间隔时间是16.7ms(即1000/60)。
大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是1000ms/60,约等于16.7ms
1.2 requestAnimationFrame的简要概念
requestAnimationFrame是HTML5中提供的动画API,简称rAF,即请求动画帧。可以让浏览器优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。
requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。
二、setTimeout与setInterval对于requestAnimationFrame的区别
setTimeout()
setTimeout()方法用来指定某个函数或字符串在指定的毫秒数之后执行。
setTimeout函数有三个参数
1. fn:(必传)需要执⾏的函数
2. time:(⾮必传)
传值时:倒计时time毫秒后执⾏fn
不传时:默认为0,fn在最早可得的空闲时间执⾏,在"任务队列"的尾部执⾏fn,因此要等到同步任务和"任务队列"现有的事件都处理
完,才会得到执⾏。
3. param:(⾮必传)fn函数的参数
不传入第三个参数:
// 以1秒为间隔 ,连续输出 5 个 6
for (var i = 1;i <= 5;i ++) {
setTimeout(function timer() {
console.log(i)
},i * 1000)
}
6
6
6
6
6
传入第三个参数
// setTimeOut 的 第三个参数 是 传给第一个函数使用
function sum(x,y,z){
console.log(x+y+z)
}
setTimeout(sum,1000,1,3,5)
输出:
9
setInterva
setInterval的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
下面的代码如果不加上clearInterval(timer),将间隔一秒无限输出 1
var timer = setInterval(function(){
console.log(1)
},1000);
clearInterval(timer)
requestAnimationFrame与以上两者的区别及它的优点
setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行
setTimeout其实就是通过一个时间间隔来不断更新图像形成的动画效果。但setTimeout在某些机型或复杂应用中会出现卡顿现象,也就是常说的“丢帧”。这事因为setTimeout只能设置固定的时间间隔,而不同的屏幕、机型会有不同的分辨率,而且setTimeout任务是被放进异步队列中的,所以实际执行时间会比设定时间晚一点。这些原因就导致了setTimeout动画的卡顿现象。
requestAnimationFrame的回调函数执行时机由系统决定,也就是说,系统每次绘制前都会主动调用requestAnimationFrame中的回调函数,如果系统绘制频率是60Hz,那回调函数就是16.7ms被执行一次,如果系统绘制频率是75Hz,那么这个时间间隔就是1000/75=13.3ms,这样就保证回调函数在每次绘制中间都能执行一次,就不会出现丢帧的现象,也不会有卡顿的问题。
requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果
三、requestAnimationFrame的简单使用
下面通过一个简单的例子来演示requestAnimationFrame的用法。
在html内设置一个圆,然后让其动起来。
cancelAnimationFrame方法来停止动画处理,圆运动到距左侧50px的时候就停下来了。
<!DOCTYPE html>
<html>
<head>
<title>requestAnimationFrame</title>
<style>
* {margin: 0;padding: 0}
.box {width: 100px;height: 100px;border-radius: 100%;background: #f00;position: absolute;left: 0;top: 0}
</style>
</head>
<body>
<div class="box" id="box"></div>
</body>
<script>
var box = document.getElementById('box')
var flag = false
var left = 0
var rAFId = ''
function render() {
if (flag) {
if (left >= 100) {
flag = false
}
box.style.left = `${left++}px`
} else {
if (left <= 0) {
flag = true
}
box.style.left = `${left--}px`
}
}
(function animloop() {
render()
rAFId = window.requestAnimationFrame(animloop)
if (left == 50) {
cancelAnimationFrame(rAFId)
}
})()
</script>
</html>
总结:
(1)requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
(2)在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
(3)requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
本人是初入前端的小菜鸟,文章如有错误,恳请大家提出问题,本人不胜感激
文章对大家有帮助的话,希望大家能动手点赞鼓励,大家未来一起努力 长路漫漫,道阻且长
转载请注明出处:https://blog.csdn.net/qq_52855464/article/details/124501174?spm=1001.2014.3001.5502