<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas烟花</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style type="text/css">
body{
padding: 0;
margin: 0;
background: #000;
}
</style>
</head>
<body>
<canvas id="canvas">Canvas is not supported in your browser.</canvas>
<script type="text/javascript">
window.requestAnimationFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback){
window.setTimeout(callback,1000/60);
}
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
cw = window.innerWidth,
ch = window.innerHeight,
fireworks = [],
particles = [],
hue = 120,
timerTotal = 80,
timerTick = 0;
canvas.width = cw;
canvas.height = ch;
function random(min,max){
return Math.random()*(max-min)+min;
}
function caculateDistance(sx,sy,tx,ty){
var xDistance = sx-tx,
yDistance = sy-ty;
return Math.sqrt(Math.pow(xDistance,2)+Math.pow(yDistance,2));
}
function Firework(sx,sy,tx,ty){
this.x = sx;
this.y = sy;
this.sx = sx;
this.sy = sy;
this.tx= tx;
this.ty = ty;
this.distanceToTarget = caculateDistance(sx,sy,tx,ty);
this.distanceTraveled = 0;
this.coordinates = [];
this.coordinatesCount = 3;
while(this.coordinatesCount--){
this.coordinates.push([this.x,this.y]);
}
this.angle = Math.atan2(ty-sy,tx-sx);
this.speed = 2;
this.acceleration = 1.05
this.brightness = random(50,70);
this.targetRadius = 1;
}
Firework.prototype.update = function(index){
this.coordinates.pop();
this.coordinates.unshift([this.x,this.y]);
if(this.targetRadius<8) {
this.targetRadius += 0.3;
} else {
this.targetRadius = 1;
}
this.speed *= this.acceleration;
var vx = Math.cos(this.angle)*this.speed,
vy = Math.sin(this.angle)*this.speed;
this.distanceTraveled = caculateDistance(this.sx,this.sy,this.x+vx,this.y+vy);
if(this.distanceTraveled>=this.distanceToTarget){
createParticles(this.tx,this.ty);
fireworks.splice(index,1);
}else{
this.x += vx;
this.y += vy;
}
}
Firework.prototype.draw = function(){
ctx.beginPath();
ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle = 'hsl('+hue+',100%,'+this.brightness+'%)';
ctx.stroke();
ctx.beginPath();
ctx.arc(this.tx,this.ty,this.targetRadius,0,Math.PI*2);
ctx.stroke();
}
function Particle(x,y){
this.x = x;
this.y = y;
this.coordinates = [];
this.coordinatesCount = 5;
while(this.coordinatesCount--){
this.coordinates.push([this.x,this.y]);
}
this.angle = random(0,2*Math.PI);
this.speed = random(1,10);
this.friction = 0.95
this.gravity = 1;
this.hue = random(hue-20,hue+20);
this.brightness = random(50,80);
this.alpha = 1;
this.decay = random(0.015,0.03);
}
Particle.prototype.update = function(index){
this.coordinates.pop();
this.coordinates.unshift([this.x,this.y]);
this.speed *= this.friction;
this.x += Math.cos(this.angle) * this.speed;
this.y += Math.sin(this.angle) * this.speed + this.gravity;
this.alpha -= this.decay;
if(this.alpha<=this.decay){
particles.splice(index,1);
}
}
Particle.prototype.draw = function(){
ctx.beginPath();
ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle = 'hsla('+this.hue+',100%,'+this.brightness+'%,'+this.alpha+')';
ctx.stroke();
}
function createParticles(x,y){
var particleCount = 30;
while(particleCount--) {
particles.push(new Particle(x,y));
}
}
function loop(){
requestAnimationFrame(loop);
hue += 0.5;
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect( 0, 0, cw, ch );
ctx.globalCompositeOperation = 'lighter';
var i = fireworks.length;
while(i--) {
fireworks[i].draw();
fireworks[i].update(i);
}
var i = particles.length;
while(i--) {
particles[i].draw();
particles[i].update(i);
}
if(timerTick >= timerTotal) {
fireworks.push(new Firework(cw/2,ch,random(0,cw),random(0,ch/2)));
timerTick = 0;
} else {
timerTick++;
}
}
window.onload = loop;
</script>
</body>
</html>
这个效果之前是在runjs上看到的,看了一段时间才看懂,根据自己的理解,较少了一些效果。
window.requestAnimationFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback){
window.setTimeout(callback,1000/60);//每秒60帧
}
})();
var canvas = document.getElementById(“canvas”),
ctx = canvas.getContext(“2d”),
cw = window.innerWidth,
ch = window.innerHeight,
fireworks = [], //烟花数组
particles = [], //烟花爆炸屑数字
hue = 120, //初始色调 0/360 红色 120 绿色 240 蓝色
timerTotal = 80, //每隔80下释放一次烟花
timerTick = 0;
//设置canvas画布的宽高
canvas.width = cw;
canvas.height = ch;
//生成min到max之间的随机数
function random(min,max){
return Math.random()*(max-min)+min;
}
//计算点(sx,sy)到点(tx,ty)之间的距离
function caculateDistance(sx,sy,tx,ty){
var xDistance = sx-tx,
yDistance = sy-ty;
return Math.sqrt(Math.pow(xDistance,2)+Math.pow(yDistance,2));
}
//烟花对象 (sx,sy)初始位置 (tx,ty)目标位置
function Firework(sx,sy,tx,ty){
this.x = sx; //实时运行坐标x
this.y = sy; //实时运行坐标y
this.sx = sx; //初始位置坐标x
this.sy = sy; //初始位置坐标Y
this.tx= tx; //目标位置坐标x
this.ty = ty; //目标位置坐标Y
this.distanceToTarget = caculateDistance(sx,sy,tx,ty); //计算初始位置到目标位置之间的距离
this.distanceTraveled = 0; //已运行距离
this.coordinates = []; //我理解是一个辅助变量 用于生成实时运动轨迹
this.coordinatesCount = 3;
while(this.coordinatesCount–){
this.coordinates.push([this.x,this.y]);
}
this.angle = Math.atan2(ty-sy,tx-sx); //初始位置和目标位置之间的角度
this.speed = 2; //初始速度
this.acceleration = 1.05 //加速度
this.brightness = random(50,70); //明度
this.targetRadius = 1; //目标位置标示圆圈的初始半径
}
//更新烟花的位置
Firework.prototype.update = function(index){
this.coordinates.pop();
this.coordinates.unshift([this.x,this.y]);
//上面是一个技巧吧 先将数组最后一个移除,然后将当前烟花位置插入到第一个,那数组最后一个元素和更新之后的坐标之间就形成了一条轨迹
//让目标标示处圆圈动起来
if(this.targetRadius<8) {
this.targetRadius += 0.3;
} else {
this.targetRadius = 1;
}
this.speed *= this.acceleration; //根据加速度变换速度
var vx = Math.cos(this.angle)*this.speed,//计算水瓶方向速度
vy = Math.sin(this.angle)*this.speed; //计算垂直方向速度
this.distanceTraveled = caculateDistance(this.sx,this.sy,this.x+vx,this.y+vy); //重新计算烟花已运行距离
//如果烟花运行距离大于或等于初始位置到目标位置之间的距离,生成新烟花并移除当前烟花,否则更新烟花位置
if(this.distanceTraveled>=this.distanceToTarget){
createParticles(this.tx,this.ty);
fireworks.splice(index,1);
}else{
this.x += vx;
this.y += vy;
}
}
Firework.prototype.draw = function(){
//画出烟花运行轨迹
ctx.beginPath();
ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle = ‘hsl(‘+hue+’,100%,’+this.brightness+’%)’;
ctx.stroke();
//画出目标位置标示小圆圈
ctx.beginPath();
ctx.arc(this.tx,this.ty,this.targetRadius,0,Math.PI*2);
ctx.stroke();
}
//烟花爆炸屑对象
function Particle(x,y){
this.x = x;
this.y = y;
this.coordinates = [];
this.coordinatesCount = 5;
while(this.coordinatesCount–){
this.coordinates.push([this.x,this.y]);
}
this.angle = random(0,2*Math.PI); //生成任意方向的碎屑
this.speed = random(1,10); //随机速度
this.friction = 0.95 //摩擦力
this.gravity = 1; //重力
this.hue = random(hue-20,hue+20); //生成与烟花色彩相近的碎屑
this.brightness = random(50,80); //随机明度
this.alpha = 1; //初始透明度
this.decay = random(0.015,0.03); //碎屑消失时间
}
Particle.prototype.update = function(index){
this.coordinates.pop();
this.coordinates.unshift([this.x,this.y]);
//上面是一个技巧吧 先将数组最后一个移除,然后将当前烟花位置插入到第一个,那数组最后一个元素和更新之后的坐标之间就形成了一条轨迹
this.speed *= this.friction;
this.x += Math.cos(this.angle) * this.speed;
this.y += Math.sin(this.angle) * this.speed + this.gravity;
this.alpha -= this.decay;
if(this.alpha<=this.decay){
particles.splice(index,1);
}
}
Particle.prototype.draw = function(){
ctx.beginPath();
ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle = ‘hsla(‘+this.hue+’,100%,’+this.brightness+’%,’+this.alpha+’)’;
ctx.stroke();
}
function createParticles(x,y){
//生成30个烟花碎屑
var particleCount = 30;
while(particleCount–) {
particles.push(new Particle(x,y));
}
}
function loop(){
//流畅动画过程
requestAnimationFrame(loop);
hue += 0.5;
ctx.globalCompositeOperation = ‘destination-out’;
ctx.fillStyle = ‘rgba(0, 0, 0, 0.5)’;
ctx.fillRect( 0, 0, cw, ch );
ctx.globalCompositeOperation = ‘lighter’;
var i = fireworks.length;
while(i–) {
fireworks[i].draw();
fireworks[i].update(i);
}
var i = particles.length;
while(i–) {
particles[i].draw();
particles[i].update(i);
}
if(timerTick >= timerTotal) {
fireworks.push(new Firework(cw/2,ch,random(0,cw),random(0,ch/2)));
timerTick = 0;
} else {
timerTick++;
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlusR">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
<style>
body{margin:0;padding:0;overflow: hidden;}
.city{width:100%;position:fixed;bottom: 0px;z-index: 100;}
.city img{width: 100%;}
</style>
</head>
<body>
<canvas id='cas' style="background-color:rgba(0,5,24,1)">canvas</canvas>
<div class="city"><img src="city.png" alt="" /></div>
<img src="moon.png" alt="" id="moon" style="visibility: hidden;"/>
<div style="display:none">
<div class="shape">HAPPY</div>
<div class="shape">HAPPY</div>
<div class="shape">HAPPY</div>
<div class="shape">HAPPY</div>
<div class="shape">HAPPY</div>
</div>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="boom.mp3" preload="auto"></audio>
<audio src="shotfire.mp3" preload="auto"></audio>
<audio src="shotfire.mp3" preload="auto"></audio>
<audio src="shotfire.mp3" preload="auto"></audio>
</body>
<script>
var cas=document.getElementById('cas'),
ctx=cas.getContext('2d'),
ocas=document.createElement('canvas'),
octx=ocas.getContext('2d'),
cw=document.compatMode=='BackCompat'?document.body.clientWidth:document.documentElement.clientWidth,
ch=document.compatMode=='BackCompat'?document.body.clientHeight:document.documentElement.clientHeight,
last,
now,
stars=[],
booms=[],
moon=document.getElementById('moon'),
shape=document.querySelectorAll('.shape'),
audio=document.getElementsByTagName('audio');
cas.width=ocas.width=cw;
cas.height=ocas.height=ch;
window.onload=function(){
createStars();
last=+new Date();
animate();
}
function animate(){
ctx.save();
ctx.globalCompositeOperation='destination-out';
ctx.globalAlpha=0.1;
ctx.fillRect(0,0,cw,ch);
ctx.restore();
stars.forEach(function(){
this.paint();
});
createMoon();
now=+new Date();
if(now-last>1000){
var rand=getRand(0,100)>50?true:false,num=Math.floor(getRand(0,shape.length)),
x=getRand(cw/3,cw*2/3),y=ch,r=2,color='#fff',tx=getRand(cw/5,cw*4/5),ty=getRand(50,ch-300);
if(rand){
booms.push(new Firework(x,y,r,color,tx,ty));
}else{
booms.push(new Firework(x,y,r,color,tx,ty,shape[num]));
}
for(var i=0;i<audio.length;i++){
if(audio[i].src.indexOf('shotfire')>=0 && (audio[i].paused || audio[i].ended)){
audio[i].play();
break;
}
}
last=now;
}
booms.forEach(function(){
var that=this;
if(!this.dead){
this.update();
this.smoke();
}else{
this.booms.forEach(function(index){
if(!this.dead){
this.update();
}else{
if(index==that.booms.length){
booms.splice(booms.indexOf(that),1);
}
}
});
}
});
requestAnimationFrame(animate);
}
function Particle(x,y,r,color,tx,ty){
this.x=x;
this.y=y;
this.r=r;
this.color=color;
this.tx=tx;
this.ty=ty;
this.dead=false;
}
Particle.prototype={
paint:function(){
ctx.beginPath();
ctx.fillStyle='rgba('+this.color.a+','+this.color.b+','+this.color.c+',1)';
ctx.fillRect(this.x-this.r,this.y-this.r,2*this.r,2*this.r);
ctx.closePath();
},
update:function(){
this.ty+=0.3;
var dx=this.tx-this.x,dy=this.ty-this.y;
if(Math.abs(dx)<0.1 && Math.abs(dy)<20){
this.dead=true;
}else{
this.x=Math.abs(dx)<0.1?this.tx:this.x+dx*0.1;
this.y=Math.abs(dy)<0.1?this.ty:this.y+dy*0.1;
this.paint();
}
}
}
function Firework(x,y,r,color,tx,ty,shape){
this.x=x;
this.y=y;
this.r=r;
this.color=color;
this.tx=tx;
this.ty=ty;
this.shape=shape || false;
this.dead=false;
this.ba=getRand(30,50);
this.booms=[];
}
Firework.prototype={
paint:function(){
ctx.save();
ctx.beginPath();
ctx.fillStyle=this.color;
ctx.arc(this.x,this.y,this.r,0,2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.restore();
},
smoke:function(){
ctx.save();
ctx.beginPath();
ctx.fillStyle='rgba(255,228,150,0.3)';
ctx.arc(this.x,this.y,this.r+Math.random()*3,0,2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.restore();
},
update:function(){
var dx=this.tx-this.x,dy=this.ty-this.y;
if(Math.abs(dx)<this.ba && Math.abs(dy)<this.ba){
this.dead=true;
if(this.shape){
this.shapeBoom();
}else{
this.boom();
}
for(var i=0;i<audio.length;i++){
if(audio[i].src.indexOf('boom')>=0 && (audio[i].paused || audio[i].ended)){
audio[i].play();
break;
}
}
}else{
this.x+=dx*0.03;
this.y+=dy*0.03;
this.paint();
}
},
boom:function(){
var count=getRand(100,300),r,color,tx,ty,angle,distance;
for(var i=0;i<count;i++){
r=getRand(1,3);
angle=getRand(-Math.PI,Math.PI);
color={
a:parseInt(getRand(0,255)),
b:parseInt(getRand(0,255)),
c:parseInt(getRand(0,255))
},
distance=getRand(0,count);
tx=Math.cos(angle)*distance+this.x;
ty=Math.sin(angle)*distance+this.y;
this.booms.push(new Particle(this.x,this.y,r,color,tx,ty));
}
},
shapeBoom:function(){
var that=this,step=4,dx=cw/2-this.tx,dy=ch/2-this.ty;
getData(this.shape,step,function(dots){
dots.forEach(function(){
that.booms.push(new Particle(that.x,that.y,1,this.color,this.x-dx,this.y-dy));
});
});
}
}
function getData(dom,step,callback){
var text=dom.innerHTML,imgData=[],dots=[],i;
octx.clearRect(0,0,cw,ch);
octx.save();
octx.font='120px 微?雅黑 bold';
octx.textAlign='center';
octx.textBaseline='middle';
octx.fillStyle='rgba('+parseInt(getRand(168,255))+','+parseInt(getRand(168,255))+','+parseInt(getRand(168,255))+',1)';
octx.fillText(text,cw/2,ch/2);
octx.restore();
imgData=octx.getImageData(0,0,cw,ch);
for(var x=0;x<imgData.width;x+=step){
for(var y=0;y<imgData.height;y+=step){
i=(y*imgData.width+x)*4;
if(imgData.data[i+3]>167){
dots.push({x:x,y:y,color:{
a:imgData.data[i],
b:imgData.data[i+1],
c:imgData.data[i+2]
}});
}
}
}
callback(dots);
}
function createMoon(){
var sx=cw-200,sy=100,r=40,add=2;
if(moon.complete){
ctx.drawImage(moon,sx,sy,2*r,2*r);
}else{
moon.onload=function(){
ctx.drawImage(moon,sx,sy,2*r,2*r);
}
}
ctx.save();
ctx.beginPath();
ctx.fillStyle='rgba(240,219,120,0.05)';
for(var i=0;i<5;i++){
ctx.arc(sx+r,sy+r,r+add,0,2*Math.PI);
ctx.fill();
add+=2;
}
ctx.closePath();
ctx.restore();
}
function createStars(){
for(var i=0;i<100;i++){
stars.push(new Star(getRand(0,cw),getRand(0,ch-200),Math.random(),'#fff'));
}
}
function Star(x,y,r,color){
this.x=x;
this.y=y;
this.r=r;
this.color=color;
}
Star.prototype={
paint:function(){
ctx.save();
ctx.beginPath();
ctx.fillStyle=this.color;
ctx.arc(this.x,this.y,this.r,0,2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.restore();
}
}
function getRand(min,max){
return Math.random()*(max-min)+min;
}
Array.prototype.forEach=function(callback){
for(var i=0;i<this.length;i++){
if(this[i]!=null){
callback.call(this[i],i);
}
}
}
</script>
</html>
鼠标点击实现
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlusR">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>?日快?</title>
<style>
*{margin:0;padding:0;list-style-type:none;}
a,img{border:0;}
body{font:12px/180% Arial, Helvetica, sans-serif, "新宋体";background:#000 url("pic.jpg") no-repeat center center;background-size: 100% 100%;}
#canvas{cursor:crosshair;display:block;color:black;}
</style>
</head>
<body>
<canvas id='canvas' width='100%' height='100%'></canvas>
<script type="text/javascript" src="lib/jquery-1.11.3.js"></script>
<script type="text/javascript">
var canvas=document.getElementById('canvas'),
ctx=canvas.getContext('2d'),
cw=window.innerWidth,
ch=window.innerHeight,
mousedown=!1,
mx,
my,
last,
now,
timerTick=0,
timerTotal=80,
timeWait=0,
timeWaitTotal=10,
fireworks=[],
particles=[],
fl,
pl,
hue=120,
accelerate=1.05,
img=new Image();
canvas.width=cw;
canvas.height=ch;
img.src='pic.jpg';
document.onmousedown=function(e){
mousedown=!0;
}
document.onmouseup=function(e){
mousedown=!1;
}
document.onmousemove=function(e){
mx=e.pageX-canvas.offsetLeft;
my=e.pageY-canvas.offsetTop;
}
window.onload=function(){
last=+new Date();
animate();
}
function animate(){
now=+new Date();
if(now-last>30){
hue=getRand(50,80);
ctx.globalCompositeOperation='destination-out';
ctx.globalAlpha=0.5;
ctx.fillRect(0,0,cw,ch);
ctx.fill();
ctx.globalCompositeOperation='lighter';
ctx.drawImage(img,0,0,cw,ch);
/*??和更新*/
fl=fireworks.length-1;
while(fl>=0){
fireworks[fl].paint();
fireworks[fl].update(fl);
fl--;
}
pl=particles.length-1;
while(pl>=0){
particles[pl].paint();
particles[pl].update(pl);
pl--;
}
/*添加?象*/
if(timerTick>timerTotal){
if(!mousedown){
fireworks.push(new Firework(cw/2,ch,getRand(0,cw),getRand(50,ch/2)));
timerTick=0;
}
}else{
timerTick++;
}
if(timeWait>timeWaitTotal){
if(mousedown){
fireworks.push(new Firework(cw/2,ch,mx,my));
timeWait=0;
}
}else{
timeWait++;
}
}
if('requestAnimationFrame' in window){
requestAnimationFrame(animate);
}else if('mozRequestAnimationFrame' in window){
mozRequestAnimationFrame(animate);
}
}
function Firework(sx,sy,tx,ty){
this.x=sx;
this.y=sy;
this.tx=tx;
this.ty=ty;
this.radius=1;
this.brightness=getRand(50,70);
this.angle=Math.atan2(this.ty-this.y,this.tx-this.x);
this.speed=5;
this.xadd=Math.cos(this.angle);
this.yadd=Math.sin(this.angle);
this.coord=[];
for(var i=0;i<3;i++){
this.coord.push({x:this.x,y:this.y});
}
}
Firework.prototype={
paint:function(){
ctx.save();
ctx.beginPath();
ctx.moveTo(this.coord[this.coord.length-1].x,this.coord[this.coord.length-1].y);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle='hsl('+hue+',100%,'+this.brightness+'%)';
ctx.lineWidth=1.5;
ctx.stroke();
ctx.beginPath();
ctx.arc(this.tx,this.ty,this.radius,0,2*Math.PI);
ctx.stroke();
ctx.closePath();
ctx.restore();
},
update:function(index){
var dx=this.tx-this.x,dy=this.ty-this.y;
if(Math.abs(dx)<20 && Math.abs(dy)<20){
fireworks.splice(index,1);
createParticles(this.x,this.y);
}else{
this.x+=this.speed*this.xadd;
this.y+=this.speed*this.yadd;
this.speed*=accelerate;
this.coord.pop();
this.coord.unshift({x:this.x,y:this.y});
if(this.radius>8){
this.radius=1;
}else{
this.radius+=0.3;
}
}
}
}
function createParticles(x,y){
for(var i=0;i<20;i++){
particles.push(new Particle(x,y));
}
}
function Particle(x,y){
this.x=x;
this.y=y;
this.hue=getRand(hue-50,hue+50);
this.brightness=getRand(50,80);
this.alpha=1;
this.decay=getRand(0.015,0.03);
this.angle=getRand(-Math.PI,Math.PI);
this.speed=getRand(5,10);
this.friction=0.95;
this.gravity=2;
this.xadd=Math.cos(this.angle);
this.yadd=Math.sin(this.angle);
this.coord=[];
for(var i=0;i<5;i++){
this.coord.push({x:this.x,y:this.y});
}
}
Particle.prototype={
paint:function(){
ctx.beginPath();
ctx.moveTo(this.coord[this.coord.length-1].x,this.coord[this.coord.length-1].y);
ctx.lineTo(this.x,this.y);
ctx.strokeStyle='hsla('+this.hue+',100%,'+this.brightness+'%,'+this.alpha+')';
ctx.lineWidth=2;
ctx.stroke();
ctx.closePath();
},
update:function(index){
this.alpha-=this.decay;
if(Math.abs(this.alpha)<=this.decay){
particles.splice(index,1);
}else{
this.x+=this.speed*this.xadd;
this.y+=this.speed*this.yadd+this.gravity;
this.speed*=this.friction;
this.coord.pop();
this.coord.unshift({x:this.x,y:this.y});
}
}
}
function getRand(min,max){
return Math.random()*(max-min)+min;
}
</script>
</body>
</html>