最近心血来潮,想写段能产生下雪效果及下彩色泡泡效果的javascript小程序,且刚看了某位大侠写的一系列用不同方法在javascript里 实现继承的文章,就想把里面的方法拿出来试下。
效果如下,点相应的按钮产生相应的效果
下彩色泡泡的主要思路是:在canvas上画数百个泡泡(随机生成泡泡的色彩,泡泡的大小,泡泡的位置),然后每隔20ms把每一个泡泡向右下方移动一段随机的距离。
下雪花的主要思路是:在canvas上画数百个雪花(随机生成雪花的大小,雪花的位置),然后每隔20ms把每一个雪花向右下方移动一段随机的距离。
因为彩色泡泡和雪花是有很多共同的属性,所以我引入了一段可以实现继承功能的javascipt代码(感谢网上某位大侠的分享)
1. 创建基类bubble的代码
this.Bubble = Class.extend({
x : null,
y : null,
r : null,
color : null,
init : function() {
this.x = Math.floor(Math.random() * canvas_width);
this.y = Math.floor(Math.random() * canvas_height);
this.r = Math.floor(Math.random() * max_r_of_snowflake);
this.color = '#'
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)];
},
draw : function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
move : function() {
this.x += Math.floor(Math.random() * max_of_x_a_step);
this.x = this.x % canvas_width;
this.y += Math.floor(Math.random() * max_of_x_a_step);
this.y = this.y % canvas_height;
}
});
2. 创建继承自基类bubble的WhiterSnowFlake的代码
this.WhiterSnowFlake = Bubble.extend({
init : function() {
this._super()
},
draw : function() {
var g1 = ctx.createRadialGradient(this.x, this.y, this.r,
this.x + max_r_of_snowflake, this.y
+ max_r_of_snowflake, 10);
g1.addColorStop(0.1, snowFlakeColorStop1);
g1.addColorStop(0.7, snowFlakeColorStop2);
g1.addColorStop(0.9, snowFlakeColorStop3);
g1.addColorStop(1, snowFlakeColorStop4);
ctx.fillStyle = g1;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
move : function() {
this._super();
}
});
3. 产生下雪的动作的代码
var setUpBackground = function() {
if (ctx) {
ctx.clearRect(0, 0, canvas_width, canvas_height);
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas_width, canvas_height);
}
};
this.moveSnowFlakes = function() {
setUpBackground();
for ( var i = 0; i < num_of_flakes; i++) {
snowFlakes[i].move();
snowFlakes[i].draw();
}
};
this.snowing = function(Class) {
if (drawSnowFlakesIntervalID) {
clearInterval(drawSnowFlakesIntervalID);
}
setUpBackground();
snowFlakes = new Array();
for ( var i = 0; i < num_of_flakes; i++) {
var a_snowFlake = new Class();
snowFlakes.push(a_snowFlake);
a_snowFlake.draw();
}
drawSnowFlakesIntervalID = setInterval("moveSnowFlakes()", 20);
};
完整的代码
<html>
<head>
</head>
<body>
<canvas id="myCanvas" width="600" height="600">ddd </canvas>
<button type="button" οnclick="snowing(WhiterSnowFlake)">下雪啦!</button>
<button type="button" οnclick="snowing(Bubble)">下彩色的泡泡啦!</button>
</canvas>
</body>
<script type="text/javascript" src="Class.js"></script>
<script type="text/javascript">
(function() {
var canvas = document.getElementById('myCanvas');
var ctx = null;
var canvas_width = 600;
var canvas_height = 600;
var max_r_of_snowflake = 10;
var max_of_x_a_step = 10;
var max_of_y_a_step = 10;
var num_of_flakes = 500;
var bgColor = "#C6E3E6";
var snowFlakeColorStop1 = 'rgb(255,255,255)';
var snowFlakeColorStop2 = 'rgb(240,240,240)';
var snowFlakeColorStop3 = 'rgb(230,230,230)';
var snowFlakeColorStop4 = 'rgb(220,220,220)';
var drawSnowFlakesIntervalID = null;
var snowFlakes = null;
if (!canvas) {
return;
}
if (canvas.getContext) {
ctx = canvas.getContext('2d');
}
if (!ctx) {
return;
}
this.Bubble = Class.extend({
x : null,
y : null,
r : null,
color : null,
init : function() {
this.x = Math.floor(Math.random() * canvas_width);
this.y = Math.floor(Math.random() * canvas_height);
this.r = Math.floor(Math.random() * max_r_of_snowflake);
this.color = '#'
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)]
+ '0123456789abcdef'[Math.floor(Math.random() * 16)];
},
draw : function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
move : function() {
this.x += Math.floor(Math.random() * max_of_x_a_step);
this.x = this.x % canvas_width;
this.y += Math.floor(Math.random() * max_of_x_a_step);
this.y = this.y % canvas_height;
}
});
this.WhiterSnowFlake = Bubble.extend({
init : function() {
this._super()
},
draw : function() {
var g1 = ctx.createRadialGradient(this.x, this.y, this.r,
this.x + max_r_of_snowflake, this.y
+ max_r_of_snowflake, 10);
g1.addColorStop(0.1, snowFlakeColorStop1);
g1.addColorStop(0.7, snowFlakeColorStop2);
g1.addColorStop(0.9, snowFlakeColorStop3);
g1.addColorStop(1, snowFlakeColorStop4);
ctx.fillStyle = g1;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
move : function() {
this._super();
}
});
var setUpBackground = function() {
if (ctx) {
ctx.clearRect(0, 0, canvas_width, canvas_height);
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas_width, canvas_height);
}
};
this.moveSnowFlakes = function() {
setUpBackground();
for ( var i = 0; i < num_of_flakes; i++) {
snowFlakes[i].move();
snowFlakes[i].draw();
}
};
this.snowing = function(Class) {
if (drawSnowFlakesIntervalID) {
clearInterval(drawSnowFlakesIntervalID);
}
setUpBackground();
snowFlakes = new Array();
for ( var i = 0; i < num_of_flakes; i++) {
var a_snowFlake = new Class();
snowFlakes.push(a_snowFlake);
a_snowFlake.draw();
}
drawSnowFlakesIntervalID = setInterval("moveSnowFlakes()", 20);
};
}());
</script>
</html>
引用的能实现继承功能的代码
( function () {
var initializing = false, fnTest = /xyz/.test( function() {
xyz;
}) ? /\b_super\b/ : /.*/;
this .Class = function () {
};
Class.extend = function (prop) {
var baseClass = null
if (this !== Class) {
baseClass = this ;
}
function F() {
if (!initializing) {
if (baseClass) {
this._superPrototype = baseClass.prototype;
}
this.init.apply( this, arguments);
}
}
if (baseClass) {
if (!initializing) {
initializing = true ;
F.prototype = new baseClass();
F.prototype.constructor = F;
initializing = false ;
}
}
for ( var name in prop) {
if (prop.hasOwnProperty(name)) {
if (baseClass && typeof (prop[name]) === 'function'
&& typeof (F.prototype[name]) === 'function'
&& fnTest.test(prop[name])) {
F.prototype[name] = (function (name, fn) {
return function () {
this._super = baseClass.prototype[name];
return fn.apply( this, arguments);
}
}(name, prop[name]))
} else {
F.prototype[name] = prop[name];
}
}
}
F.extend = arguments.callee;
return F;
}
}());