烟花源代码

<!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>

这里写图片描述

这里写图片描述

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值