文章目录
  1. 1. 效果预览 源码地址
  2. 2. 脚本动画原理
  3. 3. 什么是序列帧
  4. 4. 序列帧动画
  5. 5. 代码实现
    1. 5.1. 新建index.html文件
    2. 5.2. 分析搭建代码框架
    3. 5.3. 具体功能函数实现
  6. 6. 结语

前端写动画的情况不是很多,毕竟性能不是很好。一般网页动效,现在基本用css3就完成了。
这里说道说道 用 js脚本完成的动画。

可能很多刚入行的新手觉得写动画很复杂,有抵触心理,确实用脚本可能会涉及到一些逻辑及其设计模式,复杂的程序对技术水平要求比较高。

这里不会深入探究,只做简单引导,希望大家能快速上手写出绚丽吊炸天的动画特效.

废话太多,下面进入正题,本文先讲序列帧动画。

效果预览 源码地址

脚本动画原理

所谓动画,简单讲就是在时间轴上改动元素外貌或者位置。就好比手机拍摄视频,记录下景物的变化。

什么是序列帧

就是一帧一帧的图像文件,如这匹可爱的小马:
序列帧图

序列帧动画

把上面的小马从左到右,从上到下,播放一遍,每次展示一匹马的宽度和高度就成了动画

代码实现

为了提高性能,这里用canvas实现

新建index.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta id="viewport" name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no">
<title>序列帧动画</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<!-- 画布容器 -->
<div id="donglegend"></div>
<script type="text/javascript">
//书写脚本
</script>
</body>
</html>

分析搭建代码框架

一切从简,面向过程开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//需要一个主函数 main 作为 程序启动入口
function main(){}
//需要创建一个canvas画布
function setCanvas(){}
//需要加载图片
function loadResource(){}
// 加载完图片需要 把图片画到画布
function draw(){}
// 需要一个主循环函数,就是一个定时器,不断刷新画布
function loop(){}
// 在loop循环函数里调用 show函数(作用一会就知道了)
function show(){}
// 想想还缺少什么,为了方便画图片,可以写一个函数把图片按照区块 划分
function divideCoordinate(){}

具体功能函数实现

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
var _W = window.innerWidth,
_H = window.innerHeight,
_speed = 1000 / 10, //定时器执行频率
loopTimer = null, //保存定时器id
canvasObj = null, //画布
context = null, // 画布环境句柄
imageList = [], // 加载完图片存放地址
animateList = [], // 划分图片区域结果
animateAction = 0, // 序列帧图片第几行
animateCurframe = 0; // 序列帧图片某行第几帧
main();
function main() {
setCanvas("donglegend", _W, _H);
loadResource({
'id': 'dongsheng',
'src': 'images/dongsheng.jpg'
});
}
/**
* [setCanvas 创建画布]
* @param {[string]} id [元素容器]
* @param {[number]} w [画布宽度]
* @param {[number]} h [画布高度]
*/
function setCanvas(id, w, h) {
var object = document.getElementById(id);
object.innerHTML = '<canvas id="' + id + '_canvas" width="' + _W +'" height="'+_H+'">' +
'</canvas>';
canvasObj = document.getElementById(id + "_canvas");
context = canvasObj.getContext("2d");
}
/**
* [loadResource 加载图片]
* @param {[object]} item [{id: "xx", src: "xx"}]
*/
function loadResource(item){
var image = new Image();
image.onload = function() {
imageList[item.id] = image;
animateList = divideCoordinate(image.width, image.height, 2, 4);
loop();
}
image.src = item.src;
}
/**
* [divideCoordinate 按区域划分序列帧图片]
* @param {[type]} w [总宽度]
* @param {[type]} h [总高度]
* @param {[type]} row [总行数]
* @param {[type]} col [总列数]
* @return {[type]} [划分结果数组集]
*/
function divideCoordinate(w, h, row, col) {
var i, j, cw = w / col, ch = h / row, r = [], c;
for (i = 0; i < row; i++) {
c = [];
for (j = 0; j < col; j++) {
c.push({x : cw * j, y : ch * i, width : cw, height : ch});
}
r.push(c);
}
return r;
};
/**
* [loop 程序主循环,控制页面不断刷新]
* @return {[type]} [description]
*/
function loop() {
if (loopTimer) {
clearInterval(loopTimer);
}
loopTimer = setInterval(function() {
show();
}, _speed)
}
/**
* [show 清空画布,展示画布]
* @return {[type]} [description]
*/
function show() {
context.fillRect(0, 0, _W, _H);
draw(context, imageList['dongsheng'], animateList);
}
/**
* [draw 画图片到画布]
* @param {[type]} c [画布环境句柄]
* @param {[type]} bitmapData [图片资源]
* @param {[type]} list [划分区域数组]
*/
function draw(c, bitmapData, list) {
if(animateCurframe >= list[animateAction].length-1){
animateCurframe = 0;
animateAction++;
if(animateAction > list.length-1){
animateAction = 0;
}
}else{
animateCurframe++;
}
var p = list[animateAction][animateCurframe];
c.drawImage(
bitmapData,
p.x,
p.y,
p.width,
p.height,
(_W - p.width)/2,
(_H - p.height)/3,
p.width,
p.height
)
}

结语

至此,最简单版本的序列帧动画就完成了,可以自己下载源码修改自己想要的效果
旨在理解动画的原理,后续会详细更新 位移动画,比如小球弹跳等等。

文章目录
  1. 1. 效果预览 源码地址
  2. 2. 脚本动画原理
  3. 3. 什么是序列帧
  4. 4. 序列帧动画
  5. 5. 代码实现
    1. 5.1. 新建index.html文件
    2. 5.2. 分析搭建代码框架
    3. 5.3. 具体功能函数实现
  6. 6. 结语
顶部