這是去年聖誕節時閒著沒事, 在jsfiddle 弄的聖誕節動畫。 jsfiddle 是一個給人家寫javascript 可以馬上測試效果的地方。 每個作品都有一個連接。
完成動畫在此:
https://jsfiddle.net/87zt93sz/3/
以下大概講解如何做下雪的部分
- 首先,在html 放一個 canvas 如下:
<canvas id="cv" width="600px" height="400px"></canvas>
- 用 requestAnimationFrame 設一個循環呼喚的 timer
this.update = function() {
var cmt = this;
window.requestAnimationFrame( function() {
cmt.update();
});
}
- 下雪的animation, 每顆雪都有坐標xy, 動畫的每一tick, y 就直直下, x 則用到余弦(cos) 來控制x 左右漂浮的移動。 雪的大小也可以隨機設定 。
for ( i = 0 ; i < this.snows.length ; i++) {
this.snows[i].y += 1;
this.snows[i].x += this.snows[i].cr * Math.cos(this.snows[i].tick);
this.snows[i].tick += 0.01;
if ( this.snows[i].y > this.canvas.height ) {
this.snows[i].y = Math.random() * 50 - 50;
this.snows[i].x = Math.random() * this.canvas.width;
this.snows[i].cr = Math.random() * 2 - 1;
this.snows[i].tick = Math.random();
}
}
this.tick += 1;
this.draw();
- 在draw() 裡把每顆雪畫到canvas 上,只需要用到 * 這個符號, 用 ctx.fillText
for ( i = 0 ; i < this.snows.length ; i++ ) {
this.ctx.fillStyle = "rgba( 0 , 0 ,0, " + (i/this.snows.length) +")";
this.ctx.font = i +"px Comic Sans";
this.ctx.fillText( "*",this.snows[i].x , this.snows[i].y);
}
祝大家聖誕節愉快!
完整代碼:
function Christmas() {
this.snows = [];
this.tick = 0;
this.init = function() {
this.canvas = document.getElementById("cv");
this.canvas.style.backgroundColor = "#ffffff";
this.ctx = this.canvas.getContext('2d');
for ( i = 0 ; i < 50 ; i++ ) {
obj = {}
obj.x = Math.random() * this.canvas.width;
obj.y = Math.random() * this.canvas.height;
obj.tick = Math.random();
obj.cr = Math.random() * 4 - 2;
this.snows.push(obj);
}
this.update();
}
this.update = function() {
for ( i = 0 ; i < this.snows.length ; i++) {
this.snows[i].y += 1;
this.snows[i].x += this.snows[i].cr * Math.cos(this.snows[i].tick);
this.snows[i].tick += 0.01;
if ( this.snows[i].y > this.canvas.height ) {
this.snows[i].y = Math.random() * 50 - 50;
this.snows[i].x = Math.random() * this.canvas.width;
this.snows[i].cr = Math.random() * 2 - 1;
this.snows[i].tick = Math.random();
}
}
this.tick += 1;
this.draw();
var cmt = this;
window.requestAnimationFrame( function() {
cmt.update();
});
}
this.draw = function() {
this.ctx.clearRect( 0,0, this.canvas.width , this.canvas.height );
this.drawChrismasTree(500, 160, 20 );
this.drawChrismasTree(420, 180, 12 );
for ( i = 0 ; i < this.snows.length ; i++ ) {
this.ctx.fillStyle = "rgba( 0 , 0 ,0, " + (i/this.snows.length) +")";
this.ctx.font = i +"px Comic Sans";
this.ctx.fillText( "*",this.snows[i].x , this.snows[i].y);
}
var mrcm_fontsize = ( Math.cos(this.tick / 100 ) + 15 ) * 3 ;
this.ctx.font = mrcm_fontsize + "px Mountains of Christmas";
this.ctx.fillText( "Merry Christmas!", 170, 120);
}
this.drawChrismasTree = function( x , y , size) {
var posoffset = Math.cos(this.tick/50) * 5;
var curveoffset = Math.cos(this.tick/50) * 0.1;
for ( i = 4 ; i >= 0 ; i-- ) {
this.drawCone( x + (5 - i) * posoffset ,y + i*15 ,size+ i* 15 , (5-i)* curveoffset );
}
this.drawStar( x + 5 * posoffset ,y - size/4, size/2, size/4 , 2 * curveoffset);
}
this.drawStar = function(cx,cy,outerRadius,innerRadius , rotated_shift){
var rot = Math.PI / 2 * 3 + rotated_shift;
var x=cx;
var y=cy;
var step=Math.PI/5;
this.ctx.beginPath();
x = cx+Math.cos(rot) * outerRadius;
y = cy+Math.sin(rot) * outerRadius;
this.ctx.moveTo( x, y );
for(i = 0 ; i < 5 ;i++ ){
x = cx+Math.cos(rot) * outerRadius;
y = cy+Math.sin(rot) * outerRadius;
this.ctx.lineTo(x,y)
rot += step
x = cx+Math.cos(rot) * innerRadius;
y = cy+Math.sin(rot) * innerRadius;
this.ctx.lineTo(x,y)
rot+=step
}
x = cx+Math.cos(rot) * outerRadius;
y = cy+Math.sin(rot) * outerRadius;
this.ctx.lineTo( x, y );
this.ctx.closePath();
this.ctx.stroke();
this.ctx.fill();
}
this.drawCone = function( x, y, size , rotated_shift ) {
this.ctx.beginPath();
var cy = y + size/2;
var theta_1 = Math.PI / 4 + rotated_shift;
var theta_2 = Math.PI *3/ 4 + rotated_shift;
this.ctx.moveTo( x, y );
this.ctx.lineTo( x + size * Math.cos(theta_2),
cy + size * Math.sin(theta_2));
this.ctx.moveTo( x, y );
this.ctx.lineTo( x + size * Math.cos(theta_1),
cy + size * Math.sin(theta_1));
this.ctx.arc( x , cy , size , theta_1 , theta_2);
this.ctx.fillStyle = 'white';
this.ctx.fill();
this.ctx.strokeStyle = 'black';
this.ctx.stroke();
this.ctx.closePath();
}
}
var obj = new Christmas();
obj.init();