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