JavaScript动画实例:爆裂的粒子

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JavaScript动画实例:爆裂的粒⼦
1.⼀个粒⼦的运动
⼀个半径为3的实⼼圆以画布的中⼼(canvas.width/2,canvas.height/2)为起点,沿着⼀条曲线进⾏移动。

编写如下的HTML代码。

<!DOCTYPE html>
<html>
<head>
<title>粒⼦的运动</title>
</head>
<body>
<script>
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
var angle = 90;
var pos = [canvas.width/2,canvas.height/2];
var speed = 6;
var curve = 2.5;
var index = 1;
var color = 'rgba(69,204,255,.95)';
function draw ()
{
var radians = angle*Math.PI/180;
pos[0] += Math.cos(radians)* speed+Math.cos(index);
pos[1] += Math.sin(radians)* speed+Math.sin(index);
angle += curve;
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(pos[0],pos[1],3,0,2*Math.PI);
ctx.fill();
fade();
window.requestAnimationFrame(draw);
}
function fade ()
{
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, .03)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
window.requestAnimationFrame(draw);
</script>
</body>
</html>
View Code
在浏览器中打开包含这段HTML代码的html⽂件,可以在浏览器窗⼝中呈现出如图1所⽰的动画效果。

图1 ⼀个实⼼圆的运动
2.爆裂的粒⼦
将图1中的半径为3的实⼼圆作为⼀个基本粒⼦,抽象⼀个粒⼦对象Particle,该对象有表⽰粒⼦运动的起始位置的angle、粒⼦运动的当前位置pos(初始值为画布中⼼[canvas.width/2,canvas.height/2])、粒⼦运动速度speed、粒⼦运动⾓度变化量curve、粒⼦颜⾊color和例⼦编号index等属性;为该粒⼦对象定义move和draw两个⽅法,分别完成粒⼦的位置变化和粒⼦绘制操作。

为设定⽅便起见,给在画布中⼼爆裂的粒⼦预设置3个参数,⽤变量config来表⽰。

config.num、config.speed和config.curve分别表⽰3个参数分量。

其中,config.num表⽰画布中爆裂出的粒⼦个数,由它计算出粒⼦运动的起始位置angle;config.speed和config.curve则分别对应粒⼦运动速度speed和粒⼦运动⾓度变化量curve。

编写的HTML⽂件如下。

<!DOCTYPE html>
<html>
<head>
<title>爆裂的粒⼦</title>
</head>
<body>
<script>
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
var particles = [];
var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)',
'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)',
'rgba(178,67,255,.95)' ];
var config = {};
config.num=150;
config.speed=1;
config.curve=0.5;
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
particles.length = 0;
createParticles();
window.requestAnimationFrame(draw);
function createParticles()
{
var n = config.num;
for (var i=0; i<n; i++)
{
var angle = (360/n)*(i+1);
particles.push(new Particle(angle,i));
}
}
function draw ()
{
for (var i=0; i<particles.length; i++)
{
var p = particles[i];
p.move();
p.draw();
}
fade();
window.requestAnimationFrame(draw);
}
function Particle (angle,index)
{
this.angle = angle;
this.speed = config.speed;
this.curve = config.curve;
this.color = colors[index%5];
this.index = index;
this.pos = [canvas.width/2, canvas.height/2];
}
Particle.prototype.move = function()
{
this.angle += this.curve;
var radians = this.angle*Math.PI/180;
this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index);
this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index);
}
Particle.prototype.draw = function ()
{
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI);
ctx.fill();
}
function fade ()
{
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, .03)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
}
</script>
</body>
</html>
View Code
在浏览器中打开包含这段HTML代码的html⽂件,可以在浏览器窗⼝中呈现出如图2所⽰的动画效果,150个粒⼦包在画布中⼼爆裂开后,四散运动起来。

图2 爆裂的粒⼦(num=150,speed = 1,curve = 0.5)
为3个参数设定不同的值,可以呈现出不同的动画效果。

给出4组不同值的设定,呈现的动画效果分别如图3、图4、图5和图6所⽰。

为避免图形⽂件过⼤,下列的动画过程均只录制⼀个⽚段。

完整的动画演⽰过程请读者⾃⼰打开HTML⽂件运⾏程序观看。

图3 爆裂的粒⼦(num=300,speed = 6,curve =1.5)
图4 爆裂的粒⼦(num=300,speed = 2,curve = 1)
图5 爆裂的粒⼦(num=300,speed = 100,curve =180)
图6 爆裂的粒⼦(num=100,speed = 120,curve =10)
3.可设置参数的爆裂的粒⼦动画特效
由图2~图6可知,不同的参数设定,爆裂开来的粒⼦运动所呈现的动画效果不同。

为此,我们提供⽂本框输⼊预设数值的⽅式对3个参数的值进⾏设定,设定完成后,单击“Burst!”按钮,按设定的参数进⾏动画效果的呈现。

编写的HTML代码如下。

<!DOCTYPE html>
<html>
<head>
<title>爆裂的粒⼦(可设置参数)</title>
<style>
form
{
position:absolute;
top:0;
left:0;
z-index:100;
background-color:rgba(200,200,200,.8);
padding:8px;
font-size:90%;
}
form input[type=text]
{
width:30px;
border:1px solid #000;
text-align:center;
}
form button
{
margin:4px auto;
border:1px solid #000;
display:block;
}
</style>
</head>
<body>
<form id="settings" onsubmit="return false">
Particles<br/><input type="text" id="inNum" value="150"/><br/> Speed<br/><input type="text" id="inSpeed" value="2"/><br/>
Curve<br/><input type="text" id="inCurve" value="1"/><br/>
<button id="btnClear">Clear</button>
<button id="btnSet">Burst!</button><br/>
</form>
<script>
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
var particles = [];
var config = {};
var settings = document.getElementById('settings');
start();
window.requestAnimationFrame(draw);
function createParticles()
{
var n = config.num;
for (var i=0; i<n; i++)
{
var angle = (360/n)*(i+1);
particles.push(new Particle(angle,i));
}
}
function draw ()
{
for (var i=0; i<particles.length; i++)
{
var p = particles[i];
p.move();
p.draw();
}
fade();
window.requestAnimationFrame(draw);
}
function Particle (angle,index)
{
this.angle = angle;
this.speed = config.speed;
this.curve = config.curve;
this.color = randColor(90,255)
this.index = index;
this.pos = [canvas.width/2, canvas.height/2];
}
Particle.prototype.move = function()
{
this.angle += this.curve;
var radians = this.angle*Math.PI/180;
this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index); this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index); }
Particle.prototype.draw = function ()
{
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI);
ctx.fill();
}
function randColor(min, max)
{
var r = Math.floor(Math.random()*(max-min)+min);
var g = Math.floor(Math.random()*(max-min)+min);
var b = Math.floor(Math.random()*(max-min)+min);
return 'rgba('+r+','+g+','+b+',0.95)';
}
function fade ()
{
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, .03)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
}
function clear ()
{
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
particles.length = 0;
}
function start()
{
config.num = parseFloat(settings.inNum.value);
config.speed = parseFloat(settings.inSpeed.value);
config.curve = parseFloat(settings.inCurve.value);
createParticles();
}
settings.btnSet.addEventListener("click", start);
settings.btnClear.addEventListener("click", clear);
</script>
</body>
</html>
View Code
在浏览器中打开包含这段HTML代码的html⽂件,可以在浏览器窗⼝中呈现出如图7所⽰的动画效果。

图7 爆裂的粒⼦(单击⼀次Burst!按钮)
在页⾯中,单击“Clear”按钮,会清屏,同时置粒⼦数组的长度为0,相当于页⾯中不再有运动的粒⼦。

单击“Burst!”按钮,会读取设置的参数值,同时调⽤createParticles();向粒⼦数组中添加从画布中⼼爆裂开的粒⼦。

注意:是添加,若数组中原来有运动的粒⼦,则原来运动的粒⼦会继续运动。

这样,多次单击“Burst!”按钮,会呈现出更多有变化的动画效果。

例如,连续单击三次“Burst!”按钮,在浏览器窗⼝呈现出如图8所⽰的动画效果。

图8 爆裂的粒⼦(单击三次Burst!按钮)
4.粒⼦包在画布中⼼⾃动爆裂
从图2和图7的动画过程可以看出,⼀个粒⼦包在画布中⼼爆裂开来后,粒⼦四散运动,逐渐超出画布范围,最终画布⼀⽚空⽩。

虽然我们可以像图8的效果那样,通过不断单击“Burst!”按钮在画布中⼼爆裂开新的粒⼦包,但这需要⼈为控制。

当然,也可以不断调⽤createParticles()函数,在画布中⼼爆裂新的粒⼦包,但函数调⽤的时机需要仔细考虑。

⼀个可⾏的办法是:每当⼀个粒⼦运动超出了画布范围,可以认为该粒⼦消亡了,从particles数组中删除该粒⼦对象。

当粒⼦数组particles中剩余的粒⼦数不⾜config.num的⼀半时,⾃动调⽤createParticles()函数在画布中⼼爆裂⼀个新的粒⼦包,向粒⼦数组中添加爆裂的粒⼦。

编写的HTML⽂件如下。

<!DOCTYPE html>
<html>
<head>
<title>爆裂的粒⼦</title>
</head>
<body>
<script>
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
var particles = [];
var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)',
'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)',
'rgba(178,67,255,.95)' ];
var config = {};
config.num=150;
config.speed=1;
config.curve=0.5;
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
particles.length = 0;
createParticles();
window.requestAnimationFrame(draw);
function createParticles()
{
var n = config.num;
for (var i=0; i<n; i++)
{
var angle = (360/n)*(i+1);
particles.push(new Particle(angle,i));
}
}
function draw ()
{
for (var i=particles.length-1;i>=0; i--)
{
var p = particles[i];
p.move();
p.draw();
if (p.pos[0]<0 || p.pos[0]>canvas.width || p.pos[1]<0 || p.pos[1]>canvas.height)
particles.splice(i, 1);
}
fade();
if (particles.length<=config.num/2)
createParticles();
window.requestAnimationFrame(draw);
}
function Particle (angle,index)
{
this.angle = angle;
this.speed = config.speed;
this.curve = config.curve;
this.color = colors[index%5];
this.index = index;
this.pos = [canvas.width/2, canvas.height/2];
}
Particle.prototype.move = function()
{
this.angle += this.curve;
var radians = this.angle*Math.PI/180;
this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index);
this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index);
}
Particle.prototype.draw = function ()
{
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI);
ctx.fill();
}
function fade ()
{
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, .03)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
}
</script>
</body>
</html>
View Code
在浏览器中打开包含这段HTML代码的html⽂件,可以在浏览器窗⼝中呈现出如图9所⽰的动画效果。

图9 不断爆裂的粒⼦包
需要说明的是,对于不同的num、speed和curve三个参数的设置,上⾯的程序⼤多数情况下运⾏情况良好。

但对于如图6动画效果所设置的3个参数(num=100,speed = 120,curve =10),呈现的动画效果如图10所⽰。

图10 不断爆裂的粒⼦包(num=100,speed = 120,curve =10)
从图10看出,画⾯基本静⽌,这主要由于按给定的参数,粒⼦移动⼀次就会超出画布范围,因⽽不断删除粒⼦、添加粒⼦,每个粒⼦的移动基本是⼀次性的,即移动⼀次就超出画布范围消亡了。

⽽图6之所以可以呈现出动画效果是因为移出画布的粒⼦有可能会⾃⼰运动回来。

相关文档
最新文档