用canvas给自己的博客园加背景(二)
canvas入门(二)
前一篇大概介绍了canvas绘图的一些基础API,本文来介绍动画的部分,canvas最关键的函数是
requestAnimationFrame(callback)
。注:本文面向canvas入门人员,写的如有纰漏请指出,不喜勿喷。
requestAnimationFrame(callback)
这是一个用于制作逐帧动画的函数,在它出现之前,我们的动画基本用setTimeout或者setInterval制作。
我们可以尝试声明一个animate函数:
//这个函数会在控制台无限输出"dkplus-canvas"
(function animate() {
requestAnimationFrame(animate);
console.log("dkplus-canvas");
})();
此时打开控制台看一下效果。
可以看到animate()里面的操作在无限执行,而我们用canvas绘制动画也可以选择这样的思路,无限刷新画布,无限绘制画布。
ctx.arc(100,100,40,0,Math.PI*2,false);
ctx.stroke();
(function animate() {
requestAnimationFrame(animate);
//在同一个坐标无限循环画一个圆
//重新定义开始坐标,试着注释掉这一行看看效果有何不同
ctx.beginPath();
ctx.arc(100,100,40,0,Math.PI*2,false);
ctx.stroke();
})();
这段代码画出来的圆和只画一次的圆是有区别的,明显很多个圆叠加在一起了。
我们试着改一改代码:
//初始化坐标
var x = 100;
var y = 100;
(function animate() {
requestAnimationFrame(animate);
//重新定义开始坐标,试着注释掉这一行看看效果有何不同
ctx.beginPath();
ctx.arc(x,y,40,0,Math.PI*2,false);
ctx.stroke();
//动态修改坐标
x += 1;
y += 1;
})();
刷新画布
可以看到,这个图确实是动起来了,但是前面的图像没有被清除,而是简单的图像覆盖。所以我们要在每次绘图之前先清楚画布,使用clearRect()这个函数(可以说是canvas的橡皮擦)。
和fillRect(),strokeRect()参数一样,clearRect(x坐标,y坐标,宽度,高度):
var x = 100;
var y = 100;
(function animate() {
requestAnimationFrame(animate);
//这是我们加入的橡皮擦函数
ctx.clearRect(0,0,innerWidth,innerHeight);
ctx.beginPath();
ctx.arc(x,y,40,0,Math.PI*2,false);
ctx.stroke();
x += 1;
y += 1;
})();
保存打开浏览器,效果确实不一样了,看到的是一个圆圈在运动。
反弹条件
但是这个圆圈只会斜向下走,我们得做一些判断,让它反弹回来。比如说当圆心+半径超出浏览器边界时,我们把x+=1
变为x+= -1
。这里的1其实代表着速度,我们可以把速度储存到一个变量里,方便修改。
//我把参数都设为变量
var x = 100;
var y = 100;
var dx = 6;
var dy = 6;
var radius = 40;
(function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0,0,innerWidth,innerHeight);
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
ctx.stroke();
//当触及边界时进行反弹
if (x+radius>innerWidth || x-radius<0) {
dx = -dx;
}
if (y+radius>innerHeight || y-radius<0) {
dy = -dy;
}
x += dx;
y += dy;
})();
既然都设了变量,为何不让变量变起来呢?设为随机数可好?
//半径暂且不设随机,以后有用
var x = Math.random()*innerWidth;
var y = Math.random()*innerHeight;
var dx = Math.random()*5;
var dy = Math.random()*5;
var radius = Math.random()*40;
})();
面向对象
本人对面向对象这块不太熟,可能说的不太好请见谅
好,现在我们声明一个function为Circle,假装我们有一个Circle类,把这些变量传进去,同时把我们刚才用于绘图的、用于刷新的代码都填进去。
var x = Math.random()*innerWidth;
var y = Math.random()*innerHeight;
var dx = Math.random()*5;
var dy = Math.random()*5;
var radius = 40;
//这是一个Circle对象
function Circle(x,y,dx,dy,radius) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.raidus = radius;
//这是绘制方法
this.draw = function () {
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
ctx.stroke();
}
//这是刷新方法
this.update = function () {
if (x+radius>innerWidth || x-radius<0) {
dx = -dx;
}
if (y+radius>innerHeight || y-radius<0) {
dy = -dy;
}
x += dx;
y += dy;
//每刷新一次重新绘图
this.draw();
}
}
//new一个Circle对象
var c = new Circle(x,y,dx,dy,radius);
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0,0,innerWidth,innerHeight);
//对象c调用刷新方法
c.update();
};
animate();
多圆
现在我们已经实现了一个圆在画布上的弹跳,那么我们要怎么实现很多圆弹跳呢?
我们可以用for循环,循环随机参数,循环制造圆,循环刷新不同的圆。那么我们先引进一个圆的数组,一切都是为了方便操作:
//圆的数组
var cirleArray = [];
//循环制造不同的圆,放进数组
for (var i = 0; i < 100; i++) {
var x = Math.random()*innerWidth;
var y = Math.random()*innerHeight;
var dx = Math.random()*5;
var dy = Math.random()*5;
var radius = 40;
cirleArray.push(new Circle(x,y,dx,dy,radius));
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0,0,innerWidth,innerHeight);
//循环刷新不同的圆
for (var i = 0; i < cirleArray.length; i++) {
cirleArray[i].update();
}
};
animate();
这篇就介绍到这里,大家有兴趣可以试试,下一篇我们讲怎么用canvas进行交互。