160

用canvas给自己的博客园加背景(二) - dkplus

 6 years ago
source link: http://www.cnblogs.com/dkplus/p/7625511.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK