2024-11-16 requestAnimationFrame() 是什麼?

2024-11-16 requestAnimationFrame() 是什麼?

是的,requestAnimationFrame()JavaScript 的原生函式,由瀏覽器提供,用於執行高效的動畫或畫面刷新操作。它是專門設計來取代傳統的 setInterval()setTimeout() 進行動畫更新的,提供了更好的性能和流暢度。


1. requestAnimationFrame() 是什麼?

requestAnimationFrame() 的作用是:

  • 告訴瀏覽器:在下一次屏幕重繪之前執行一段指定的函式。
  • 瀏覽器會根據屏幕的刷新率(通常是每秒 60 次,等於 16.66 毫秒一次)來調整執行頻率,確保動畫更新的效率和流暢性。

2. 語法

1
let requestID = requestAnimationFrame(callback);

參數

  • callback: 你想要執行的函式,會在每次屏幕重繪時被調用。

返回值

  • requestID: 一個數字標識符,用於取消這次動畫請求(配合 cancelAnimationFrame())。

3. 簡單範例

以下是一個使用 requestAnimationFrame() 實現簡單動畫的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
let start = null;

function step(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;

console.log(progress); // 每次刷新時輸出經過的時間
if (progress < 2000) { // 動畫持續 2 秒
requestAnimationFrame(step);
}
}

requestAnimationFrame(step);

解釋:

  1. timestamp: 由瀏覽器傳入,表示從頁面加載到現在的時間(以毫秒為單位)。
  2. step 函式中,我們計算時間進度 progress,並根據進度執行動畫邏輯。

4. requestAnimationFrame() 的優勢

相比於 setInterval()setTimeout()requestAnimationFrame() 的優勢如下:

1. 同步屏幕刷新率

  • requestAnimationFrame() 自動根據屏幕刷新率調整執行頻率,通常每秒 60 次(約 16.66 毫秒一次),可以保證動畫的流暢性。

2. 節省資源

  • 在頁面不可見或不活動時(比如切換到其他標籤頁),瀏覽器會暫停動畫執行,減少不必要的資源消耗。

3. 更精確的時間間隔

  • requestAnimationFrame() 的執行時機比 setInterval() 更準確,因為它直接集成到瀏覽器的重繪機制中。

4. 避免卡頓

  • 使用 requestAnimationFrame() 可以減少掉幀的情況,讓動畫更平滑。

5. 在碼錶中使用 requestAnimationFrame()

如果你想用 requestAnimationFrame() 來實現碼錶功能,可以這樣做:

碼錶範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let start = null;
let elapsed = 0; // 經過的時間

function updateTimer(timestamp) {
if (!start) start = timestamp;
elapsed = timestamp - start;

console.log(Math.floor(elapsed)); // 輸出經過的時間(毫秒)

if (elapsed < 10000) { // 計時到 10 秒為止
requestAnimationFrame(updateTimer);
}
}

requestAnimationFrame(updateTimer);

對應的 Vue 實現

在 Vue 中,可以這樣整合 requestAnimationFrame()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export default {
data() {
return {
time: 0,
startTime: null,
timerID: null,
};
},
methods: {
startTimer() {
const updateTime = (timestamp) => {
if (!this.startTime) this.startTime = timestamp;
this.time = Math.floor(timestamp - this.startTime);

// 繼續請求下一幀
this.timerID = requestAnimationFrame(updateTime);
};

this.timerID = requestAnimationFrame(updateTime);
},
stopTimer() {
cancelAnimationFrame(this.timerID); // 停止動畫
this.timerID = null;
},
resetTimer() {
this.stopTimer();
this.time = 0;
this.startTime = null;
},
},
};

6. 總結

requestAnimationFrame() 是 JavaScript 原生的高效動畫工具,適合用於實現:

  • 動畫
  • 動態數字變化
  • 時間計算等

在碼錶中,它可以作為 setInterval() 的替代方案,提供更加流暢和高效的更新機制。