d
k
p
l
u
s

用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进行交互。

posted @ 2017-10-04 13:11  dkplus  阅读(2695)  评论(28编辑  收藏  举报