每周一点canvas动画
好吧!各位骚年们,《每周一点canvas动画》是一个系列文章,该系列文章并不对canvas的API做过多的介绍,我默认你已经了解基本的canvas绘图API,并在此告诉你如何使用简单的数学与物理知识创建相当酷炫的动画。一说到物理和数学知识各位骚年们是不是感觉蛋疼(原谅我说脏话了),不过我要告诉你,我们用到的数学和物理知识真的很简单。所以,给位骚年不要害怕,我们一起飞如何!
关于canvas是个什么东西,在这我就不做过多的介绍了,随便在度娘上搜一搜,关于canvas的概念啊,API什么的就都有了。那么我们接下来就要开始介绍,动画(animation)是怎样形成的?。动画其实是由不同的静态画面组成,每一幅静态画面我们叫做一帧(frame),当众多的静态画面按照一定的规则快速运动时,我们的眼睛就会欺骗我们的大脑,从而形成物体运动的假象。
canvas作为H5中最为重要的新增特性,使开发者可以用它来创作各种令人惊叹的作品。但开发者最关心的问题肯定是浏览器的支持情况啊!
另外需要知道的是本系列文章主要介绍Canvas 2D动画,关于 3D 动画(webGL)暂时还不涉及。好的接下来,进入重点内容。首先是我们创作动画的基本文档结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<canvas id="canvas" width='500' height="500">
<P>you browser not support canvas!</P>
</canvas>
<script>
window.onload = function(){
//我们的代码
}
</script>
</body>
</html>
以上代码就是我们创建动画的主要文档结构。那么为了对Canvas动画有个更加直观的认识,在这里先给大家展示用Canvas创作的两个酷炫动画,看看它是否够简洁,够酷炫!
1、百分比加载
第一个动画是一个用Canvas做的百分比加载动画,效果图如下:
具体代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>百分比加载</title>
</head>
<body>
<canvas id="canvas" width="500" height="500" style="background:#000;"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas'), //获取canvas元素
context = canvas.getContext('2d'), //获取画图环境,指明为2d
centerX = canvas.width/2, //Canvas中心点x轴坐标
centerY = canvas.height/2, //Canvas中心点y轴坐标
rad = Math.PI*2/100, //将360度分成100份,那么每一份就是rad度
speed = 0.1; //加载的快慢就靠它了
//绘制蓝色外圈
function blueCircle(n){
context.save();
context.strokeStyle = "#49f"; //设置描边样式
context.lineWidth = 5; //设置线宽
context.beginPath(); //路径开始
context.arc(centerX, centerY, 100 , -Math.PI/2, -Math.PI/2 +n*rad, false); //用于绘制圆弧context.arc(x坐标,y坐标,半径,起始角度,终止角度,顺时针/逆时针)
context.stroke(); //绘制
context.closePath(); //路径结束
context.restore();
}
//绘制白色外圈
function whiteCircle(){
context.save();
context.beginPath();
context.strokeStyle = "white";
context.arc(centerX, centerY, 100 , 0, Math.PI*2, false);
context.stroke();
context.closePath();
context.restore();
}
//百分比文字绘制
function text(n){
context.save(); //save和restore可以保证样式属性只运用于该段canvas元素
context.strokeStyle = "#49f"; //设置描边样式
context.font = "40px Arial"; //设置字体大小和字体
//绘制字体,并且指定位置
context.strokeText(n.toFixed(0)+"%", centerX-25, centerY+10);
context.stroke(); //执行绘制
context.restore();
}
//动画循环
(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
whiteCircle();
text(speed);
blueCircle(speed);
if(speed > 100) speed = 0;
speed += 0.1;
}());
}
</script>
</body>
</html>
在上面的代码段中,我们通过一个立即执行函数来执行我们的动画循环,并在内部通过
window.requestAnimationFrame(drawFrame, canvas);
循环调用自身,requestAnimationFrame是一个新的API,作用与setTimeInterval一样,不同的是它会根据浏览器的刷新频率自动调整动画的时间间隔。在循环中我们每次执行都会重新绘制蓝色的圆弧,和白色的圆环和百分比加载的文字,由于每次绘制的时间间隔很小,只有十几毫秒(主要看电脑),所以我们的肉眼是无法清楚地分别每一帧的画面,这样就形成了我们看到的动画。试一试吧!看看够不够酷炫!
2、黑客帝国(Matrix)
好吧!这个动画效果,就如标题所示,是一个绝对的酷炫动画效果,具体是不是在黑客帝国里出现过我也忘了,因为实在是比较早的电影。废话不多说,上效果图:
具体代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Martrix</title>
<style>
body{
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="canvas" style="background:#000;"></canvas>
<script>
window.onload = function(){
var canvas = document.querySelector('canvas'),
context = canvas.getContext('2d'),
w, h;
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
//初始化
var clearColor = 'rgba(0, 0, 0, .1)', //用于绘制渐变阴影
wordColor = "#33ff33", //文字颜色
words = "0123456789qwertyuiopasdfghjklzxcvbnm,./;'\\[]QWERTYUIOP{}ASDFGHJHJKL:ZXCVBBNM<>?",
wordsArr = words.split(''), //将文字拆分进一个数组
font_size = 16, //字体大小
clumns = w / font_size, //文字降落的列数
drops = [];
for(var i=0; i<clumns; i++){
drops[i] = 1;
}
function draw(){
context.save();
context.fillStyle = wordColor;
context.font = font_size + "px arial";
//核心
for (var i = 0; i < drops.length; i++){
var text = wordsArr[Math.floor(Math.random() * wordsArr.length)];
context.fillText(text, i * font_size, drops[i] * font_size);
if (drops[i] * font_size > h && Math.random() > 0.98){
drops[i] = 0;
}
drops[i]++;
}
context.restore();
}
//动画循环
(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
context.fillStyle = clearColor;
context.fillRect(0, 0, w, h);
draw();
}())
//resize
function resize(){
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;``
}
canvas.addEventListener("resize", resize);
}
</script>
</body>
</html>
这段代码有两个比较核心的地方:
1,在初始化部分,我们定义了一个变量clearColor = ‘rgba(0, 0, 0, .1)’,用处就和注释一样,用于绘制阴影,它的主要用处在动画循环部分。原理可以这样理解:我们每画新的一帧,就在上面覆盖一个透明度为0.1的矩形模块,这样就形成了我们看到的阴影,是不是很简单呢?
2,在初始化的注释处和核心模块处,这部分的原理是这样:首先我们设置了每个字体的大小(font_size),然后,用canvas的宽度除以字体的大小,我们就得到了需要绘制的列数(clumns), 然后创建了一个数组drops,数组的长度为clumns,并且每个元素的值都为1(drops在这有什么用呢?继续往下看)。
在绘制部分,我们采取的思路是一行一行的绘制,首先在循环中随机的获取文字,在文字绘制API部分注意这行代码:
context.fillText(text, i * font_size, drops[i] * font_size);
我们知道该API有三个参数,第一个是绘制的文字,第二,三是文字的坐标。在X坐标部分为i * font_size
,也就是说在循环完成后每个文字的X轴坐标是(0, 16, 32,48…), 而Y坐标为drops[i] * font_size
由于drops内元素的初始值都为1,所以文字的Y坐标为(16, 16, 16, …),这样我们就相当于先绘制了第一行的文字。那么紧接着我们绘制第二行只需要将drops中的元素加1即可,即(第二行的Y轴坐标为(32,32,32…))。
依次类推,我们就绘制了满屏的文字,通过渐变阴影我们就可以看到文字似乎是向下运动的效果。为了让他们看上去运动的速度不一致,我们加上了这行代码:
if (drops[i] * font_size > h && Math.random() > 0.98){
drops[i] = 0;
}
这行代码我们,判断的是当前绘制的这行文字的Y坐标是否超过了canvas的高度,如果超过又从第一行开始绘制,那么如何让他们出现差异性呢!小秘密在Math.random() > 0.98
这,if中的两个条件一个是判断文字高度,另一个是判断一个随机数是佛大于0.98,只有当两个条件同时成立才能回到第一行重新绘制。所以,由于第二个条件是随机的,那么差异性就自然而然的出现了!
看看,只需要这么简单的代码就能写出这么酷炫的效果,是不是很赞!你也试试吧!不理解没关系,这里只是让你看看canvas能做出多么酷炫的效果。如果,有什么不懂的地方可以,评论哦。
下一节,我们就正式开始我们的Canvas动画之旅!!!
【您可能感兴趣的文章】
前端圈--打造专业的前端技术会议
为web前端开发者提供技术分享和交流的平台
打造一个良好的前端圈生态,推动web标准化的发展
官网:http://fequan.com
微博:fequancom | QQ群:41378087
长按二维码关注我们
投稿:content@fequan.com
赞助合作:apply@fequan.com