>本小節主要講述動畫幀率相關內容
<br />
### 使用chrome開發者工具performance

<br />

第二張圖顯示的是幀率相關的內容,綠色的柱狀條跟動畫的幀率有關,越高說明幀率越高,紅色的為動畫卡頓。
<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)
```