# Web的一些常用API
# window.requestAnimationFrame()
执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
WARNING
若想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()
。
该API
返回一个long
整数,请求ID
,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给window.cancelAnimationFrame()
以取消回调函数。
function setInterval(callback, interval) {
let timer
const now = Date.now
let startTime = now()
let endTime = startTime
const loop = () => {
timer = window.requestAnimationFrame(loop)
endTime = now()
if (endTime - startTime >= interval) {
startTime = endTime = now()
callback(timer)
}
}
timer = window.requestAnimationFrame(loop)
return timer
}
let a = 0
setInterval(timer => {
console.log(1)
a++
if (a === 3) cancelAnimationFrame(timer)
}, 1000)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
首先
requestAnimationFrame
自带函数节流功能,基本可以保证在16.7
毫秒内只执行一次(不掉帧的情况下),并且该函数的延时效果是精确的,没有其他定时器时间不准的问题,当然你也可以通过该函数来实现setTimeout
。
TIP
利用setTimeout
实现动画效果,容易出现卡顿,抖动的现象。原因是:setTimeout
任务被放入异步队列,只有当主线程任务执行后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;setTimeout
的固定时间间隔不一定与屏幕刷新时间相同,会引起丢帧。
requestAnimationFrame
:优势:由系统决定回调函数的执行时机。60Hz
的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。在高频率事件(resize/scroll
等)中,为了防止在一个刷新间隔内发生多次函数执行,可以保证每个刷新时间间隔内,函数只被执行一次,这样既能保证流畅性,也能更好节省函数执行的开销。
使用
setTimeout
实现的动画,当页面被隐藏或最小化时,setTimeout
仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU
资源。而requestAnimationFrame
则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame
也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU
开销。在大多数浏览器中setTimeout
和setInterval
未被激活的tabs的定时最小延迟>=1000ms
,浏览器为了优化后台tab的加载损耗(以及降低耗电量),在未被激活的tab中定时器的最小延时限制为1S(1000ms)
。为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame()
运行在后台标签页或者隐藏的iframe
里时,requestAnimationFrame()
会被暂停调用以提升性能和电池寿命。
实现window.requestAnimationFrame
的polyfill
if(!window.requestAnimationFrame) {
window.requestAnimationFrame = (callback,element) => {
const id = window.setTimeout(() => {
callback()
},1000/60)
return id
}
}
if(!window.cancelAnimationFrame) {
window.cancelAnimationFrame = id => {
clearTimeout(id)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
← 事件 JavaScript的错误处理和调试 →