>本小节主要讲述动画帧率相关内容
<br />
### 使用chrome开发者工具performance
![](https://box.kancloud.cn/0c375e328842bd967a62d19166f16c5c_1439x503.png)
<br />
![](https://box.kancloud.cn/6009a01081c3631957da1672d763dec1_1439x197.png)
第二张图显示的是帧率相关的内容,绿色的柱状条跟动画的帧率有关,越高说明帧率越高,红色的为动画卡顿。
<br />
### 相关api
#### window.requestAnimationFrame()
用来将某一动画放置在下一次渲染时执行,在页面同时处理很多动画的情况下可以提交动画的帧率。
举个🌰:比如循环某一dom元素数组,讲其高度提高至原来的两倍
```javascript
function doubleHeight(element) {
let currentHeight = element.clientHeight;
element.style.height = (currentHeight \* 2) + 'px';
}
elements.forEach(doubleHeight);
```
上面代码的问题在于,for循环的速度很快,导致在一个渲染中出现很多个提高高度的动画,导致页面性能降低,可以通过使用该api进行改进
```javascript
function doubleHeight(element) {
let currentHeight = element.clientHeight;
window.requestAnimationFrame(() => {
element.style.height = (currentHeight \* 2) + 'px';
})
}
elements.forEach(doubleHeight);
```
该api接受一个回调函数,回调函数将在下一次渲染时执行,这样我们就将多次并行的渲染改成了串行的渲染,该api多用于对动画的渲染速度的调节;
例如我们在页面滚动要执行一些动画
```javascript
window.onscroll = function () {
window.requestAnimationFrame(/\*回调函数\*/)
}
```
例如使元素每一帧旋转一度
```javascript
let targetEle = document.getElelementById('demo');
function rotateFn (arc) {
targetEle.style.transform = `rotate: ${arc}deg`;
// eslint不推荐使用++或者--的方式,建议养成这个习惯
window.requestAnimationFrame(rotateFn(arc += 1))
}
window.requestAnimationFrame(rotateFn(0))
```
#### window.requestIdleCallback( ) - 只有chrome有
该方法用于将动画放置在页面渲染空闲时间执行,可以分摊动画渲染高峰时期的渲染引擎的压力,当只有帧的末尾有空闲时间时,回调才会执行。
其接受两个参数,第一个时要执行的回调函数,第二是时间,用于强制设定渲染时间。通过设定第二个时间可以实现设定时间内没有空闲时间去渲染时,会强制渲染,无需继续等待。
```javascript
// 在3s内如果一直在等待渲染,那么3s后将强制渲染,不再等待。
window.requestIdleCallback(() => {
// ...动画效果
}, 3000)
```
同时,第一个回调函数可以接受一个名为deadline的对象作为参数,该对象有两个属性,分别为timeRemaining()和didTimeout
- deadline.timeRemaining( )是一个只读方法,用于返回当前帧后剩余的毫秒数,可以用于判断当前帧是否有时间去执行我们要执行的动画
- didTimeout返回一个布尔值,用于表明我们指定的时间是否到期。
在实际使用中会将这两个参数结合起来使用
```javascript
function runAnimation (deadline) {
// 如果帧后剩余时间大于0或者设定的时间已经到期,立即执行动画
if (deadline.timeRemaining() > 0 || deadline.didTimeout) {
//...执行动画
}
// 否则就将动画放到下一帧去执行
else {
window.requestIdleCallback(runAnimation(deadline))
}
}
window.requestIdleCallback(runAnimation(deadline), 3000)
```