Appearance
requestAnimationFrame
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
语法
js
window.requestAnimationFrame(callback);
window.requestAnimationFrame(callback);
1
参数
callback:下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入DOMHighResTimeStamp
参数,该参数与performance.now()
的返回值相同,它表示requestAnimationFrame()
开始去执行回调函数的时刻。
返回值
一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给 window.cancelAnimationFrame()
以取消回调函数。
应用
对应关键代码
vue
<template>
<div class="btn-group">
<button class="btn" @click="onStart">开始</button>
<button class="btn" @click="onStop">停止</button>
<button class="btn" @click="onReset">重置</button>
</div>
<div class="box" :ref="el => boxRef = (el as HTMLElement)"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const boxRef = ref<HTMLElement | null>(null)
let animationId: number
// 开始
const onStart = () => {
let start: number;
const step: FrameRequestCallback = (timestamp) => {
const box = boxRef.value
if (box) {
if (start === undefined) {
start = timestamp;
}
// 3秒走完的进度
const progress = Math.ceil((timestamp - start) / 3000 * 100)
if (progress < 100) {
box.style.width = `${progress}%`;
animationId = requestAnimationFrame(step)
}
}
}
animationId = requestAnimationFrame(step)
}
// 暂停
const onStop = () => {
cancelAnimationFrame(animationId);
}
// 重置
const onReset = () => {
cancelAnimationFrame(animationId);
requestAnimationFrame(() => {
boxRef.value?.style.setProperty('width', "0%")
})
}
</script>
<template>
<div class="btn-group">
<button class="btn" @click="onStart">开始</button>
<button class="btn" @click="onStop">停止</button>
<button class="btn" @click="onReset">重置</button>
</div>
<div class="box" :ref="el => boxRef = (el as HTMLElement)"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const boxRef = ref<HTMLElement | null>(null)
let animationId: number
// 开始
const onStart = () => {
let start: number;
const step: FrameRequestCallback = (timestamp) => {
const box = boxRef.value
if (box) {
if (start === undefined) {
start = timestamp;
}
// 3秒走完的进度
const progress = Math.ceil((timestamp - start) / 3000 * 100)
if (progress < 100) {
box.style.width = `${progress}%`;
animationId = requestAnimationFrame(step)
}
}
}
animationId = requestAnimationFrame(step)
}
// 暂停
const onStop = () => {
cancelAnimationFrame(animationId);
}
// 重置
const onReset = () => {
cancelAnimationFrame(animationId);
requestAnimationFrame(() => {
boxRef.value?.style.setProperty('width', "0%")
})
}
</script>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47