这个是《html5实验室-Canvas世界》中的一个例子,最大的收获当然是心形函数(x ^ 2 + y ^ 2 - 1) - x ^ 2 * y ^ 3 = 0。
有了前面几个动画做铺垫,这个还是比较容易就完成了,没有遇到什么奇特的问题。不过也因为比较轻松,代码的组织不是很认真,也不想去改了。
值得一提的是这个动画很容易另行发挥,我在调试的过程之中也看到了几个很有意思的版本。有一个版本将粒子生成点扩大到全局,这样配合inHeart函数一闪即逝,会有小星星的效果。另一个版本因为几个巧合把粒子生成点放到了画布右下角,而且方向都在第二象限,造成了从右下角喷射粒子的效果。
<!DOCTYPE html>
<html>
<head>
<title>♥</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script type = "text/javascript">
var limit = 300;
var unit = 200;//心形线单位一
var width = 800,
height = 600;
var ctx = null;
var balls = [];
var side = [];
function inHeart(b){
//(x ^ 2 +y^ 2 - 1) - x ^ 2 * y ^ 3 == 0,心形函数
var x = b.x / unit;
var y = -b.y / unit;//因为坐标y轴是向下的
var part = x * x + y * y - 1;
return (part * part * part < x * x * y * y * y);
}
function randomColor(){
var x = Math.floor(Math.random() * 155) + 100;
var y = Math.floor(Math.random() * 155) + 100;
var z = Math.floor(Math.random() * 155) + 100;
return "rgb(" + x + "," + y + "," + z + ")";
}
function createBall(){
return {
x : (Math.random() - Math.random()) * width * 0.1,
y : (Math.random() - Math.random()) * height * 0.2 - height * 0.1,
vx : (Math.random() - Math.random()) * 7,
vy : (Math.random() - Math.random()) * 7,
r : Math.random() * 5,
color : randomColor()
}
}
function init(){
var cvs = document.createElement("canvas");
cvs.width = width;
cvs.height = height;
ctx = cvs.getContext("2d");
ctx.translate(width / 2, height / 2);
document.body.appendChild(cvs);
for(i = 0; i < limit; i++){
balls.push(createBall());
}
for(i = 0; i < limit / 5; i++){
side.push(undefined);
}
}
function drawBall(ctx, ball){
ctx.fillStyle = ball.color;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
}
function start(){
document.body.removeChild(document.getElementById("start"));
setInterval(function(){
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
ctx.fillRect(-width / 2, -height / 2, width, height);
for(i in balls){
var b = balls[i];
drawBall(ctx, b);
b.x += b.vx;
b.y += b.vy;
if(!inHeart(b)){
side[Math.floor(Math.random() * side.length)] = balls[i];
balls[i] = createBall();
}
}
for(var i in side){
var b = side[i];
if(b != undefined){
drawBall(ctx, b);
}
}
}, 33);
}
</script>
</head>
<body onload = "init();">
<button id = "start" onclick = "start();">click me!</button>
<br />
</body>
</html>