有一种动画书,就是快速翻动就可以看见里面的内容运动起来了。电脑动画和这个差不多,通过在动画区域内用一张新的图片代替旧的图片,并快速持续的改变,根据视觉暂留现象就在我们的大脑中形成了动画。

HTML5里面,我们通过下面的语句来实现画面的更替:

1
window.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="Author" content="sunsi">
<meta name="Keywords" content="webgl,animation">
<meta name="Description" content="webgl tutorial from blog.techcave.cn">
<script type="text/javascript">
<!--
var cv, ctx;
function init() {
//1. 获取canvas元素
cv = document.getElementById("cv");
//2. 获取2D上下文
ctx = cv.getContext('2d');
//3. 其他的准备初始化工作
//4. 开始我们的动画
window.requestAnimationFrame(animation)
}

function animation() {
//1. 移走前一个画面
removePrevFrame();
//2. 放上一个新画面
newFrame();
//3. 持续的更新
window.requestAnimationFrame(animation)
}
function removePrevFrame() {
//清空画布,比较简单的方法是clearRect
ctx.clearRect(0,0,300,300);
}
function newFrame() {
//根据当前的状态载入新的画面
}
//-->
</script>
<title>Document</title>
</head>

<body onload="init()">
<canvas id="cv" width="600" height="600"></canvas>
</body>

</html>

首先,我们通过init方法绑定到body的onload事件,实现整个webgl画布和其他的初始化。里面关键第4点,使用 window.requestAnimationFrame语句来实现画面的刷新,该语句有个参数是个回调函数,在该函数中实现刷新逻辑,这里我们编写了animation方法实现。该回调方法通常、大致做几件事情:把冰箱门打开、把原来的大象拿出来,(读者:说人话。作者:请看注释)。好了,言归正传,是不是很简单。根据这个思路,我们把这个代码完善一下,画一根秒针——旋转的金箍棒。

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="Author" content="sunsi">
<meta name="Keywords" content="webgl,animation">
<meta name="Description" content="webgl tutorial from blog.techcave.cn">
<script type="text/javascript">
<!--
var cv, ctx;
var lastSeconds;

function init() {
//1. 获取canvas元素
cv = document.getElementById("cv");
//2. 获取2D上下文
ctx = cv.getContext('2d');
//3. 其他的准备初始化工作
//4. 开始我们的动画
window.requestAnimationFrame(animation)
}

function animation() {
//1. 移走前一个画面
removePrevFrame();
//2. 放上一个新画面
newFrame();
//3. 持续的更新
window.requestAnimationFrame(animation)
}

function removePrevFrame() {
//清空画布,比较简单的方法是clearRect
//保存当前状态,每次刷新都以该状态开始
ctx.save();
ctx.clearRect(0, 0, 400, 400);
}

function newFrame() {
//根据当前的状态载入新的画面
var now = new Date();

ctx.translate(200, 200);
var sec = now.getSeconds();
//这里保存平移状态,意思原点移动到200,200并保持住
ctx.save();
ctx.rotate(sec * Math.PI / 30); //360 * sec / 60 * Math.PI / 180
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(150, 0);
ctx.stroke();
//弹出状态栈,要不每个循环都会在上次基础上平移旋转
ctx.restore();
ctx.restore()
}
//-->
</script>
<title>Document</title>
</head>

<body onload="init()">
<canvas id="cv" width="600" height="600"></canvas>
</body>

</html>

效果如下所示:

秒针转动的线条