h5 canvas+js实现烟花效果

又快过年了,作为一名程序员,我想用自己的方式祝大家新年快乐,下图是移动端访问截图,pc端也可以访问,点击图片预览效果

这个效果是用h5的canvas+js实现的,主要技术点是如何实现一个烟花爆炸的模型,而不是如何绘制出图形图像,例如,为了逼真的模拟烟花爆炸过程中的细节,我们会发现烟花爆炸后的各个方向上运动的烟火都会有一个“尾巴”,从爆炸到烟花的消失,是一个渐变的过程,不是一下子就消失了,爆炸时,中心到爆炸边缘的粒子运动是一个口向下的二次函数。


以下是关键代码:

[html] view plain copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"  />  
  5. <script type="text/javascript" src="jquery.min.js"></script>  
  6. <style>  
  7. body{  
  8.     margin:0px;  
  9.     padding:0px;  
  10. }  
  11. html{  
  12.     margin:0px;  
  13.     padding:0px;  
  14. }  
  15. </style>  
  16. <script>  
  17. var screeWidth;  
  18. var screeHeight;  
  19. var img;  
  20. var my_canvas;   
  21. var context;    
  22.   
  23. var size = 3;  
  24. //弧度常量  
  25. var  radis = Math.PI /180;  
  26. //精灵粒子,全局的  
  27. var spriteArray = new Array();  
  28. //创建烟花队列  
  29. var gloablYanhuaArray = new  Array();  
  30. gloablYanhuaArray.push( YANHUAOBJ(800,400,50,size,0));  
  31. gloablYanhuaArray.push( YANHUAOBJ(200,400,50,size,1));  
  32. //gloablYanhuaArray.push( YANHUAOBJ(400,400,50,size));  
  33.   
  34. $(function() {   
  35.     img = document.getElementById("tulip");   
  36.     my_canvas=$("#myCanvas");     
  37.     screeWidth = window.innerWidth;  
  38.     screeHeight = window.innerHeight;  
  39.     $("#myCanvas").attr("width",screeWidth);  
  40.     $("#myCanvas").attr("height",screeHeight);  
  41.     my_canvas=my_canvas[0];  
  42.     context=my_canvas.getContext("2d");    
  43.     setInterval("draw()",80);  
  44.     setInterval("explod()",500);  
  45.     window.addEventListener( 'resize', onWindowResize, false );  
  46.     });    
  47. function onWindowResize(){  
  48.     alert(1);  
  49. }  
  50. function clearg(){  
  51.     for(var i = 0; i< gloablYanhuaArray.length;i++){  
  52.         if(gloablYanhuaArray[i].dead){  
  53.             gloablYanhuaArray.splice(i,1);  
  54.         }  
  55.     }  
  56. }  
  57. function draw(){  
  58.     //console.log("精灵总数:"+spriteArray.length+",大烟花:"+gloablYanhuaArray.length);  
  59.     clearg();  
  60.     context.clearRect(0,0,my_canvas.width,my_canvas.height);  
  61.     context.fillStyle   = "#fff";;  
  62.     context.fillText("当前烟花数:"+gloablYanhuaArray.length+",当前粒子数:"+spriteArray.length,100,100);  
  63.     context.drawImage(getCatcheCanvas(),0,0,screeWidth,screeHeight);  
  64.           
  65. }     
  66. //缓存绘图  
  67. function getCatcheCanvas(){  
  68.     var canvas = document.createElement( 'canvas' );  
  69.     canvas.width = screeWidth;  
  70.     canvas.height = screeHeight;  
  71.     var context = canvas.getContext( '2d' );  
  72.     context.clearRect(0,0,canvas.width,canvas.height)  
  73.     //绘制粒子  
  74.     for(var j=0;j<spriteArray.length;j++){  
  75.       
  76.     var bb = spriteArray[j].color;  
  77.         var color = bb.substring(0,bb.lastIndexOf(","))+","+spriteArray[j].alpha+")";  
  78.         //var color = "rgba(255,255,255,"+spriteArray[j].alpha+")";  
  79.         //color=spriteArray[j].color;  
  80.         context.fillStyle   = color  
  81.         var csize = spriteArray[j].size;  
  82.         context.beginPath();  
  83.         context.fillRect(spriteArray[j].x-csize/2,spriteArray[j].y-csize/2,spriteArray[j].size,spriteArray[j].size);  
  84.         //context.arc(spriteArray[j].x,spriteArray[j].y,spriteArray[j].size,0,Math.PI*2,true);  
  85.         //context.drawImage(generateSprite(color,spriteArray[j].alpha),spriteArray[j].x,spriteArray[j].y,spriteArray[j].size,spriteArray[j].size)  
  86.         //context.drawImage(document.getElementById("tulip"),spriteArray[j].x,spriteArray[j].y,25,25);  
  87.         context.closePath();  
  88.         context.fill();;  
  89.         if(spriteArray[j].deaded){  
  90.             spriteArray.splice(j,1);;  
  91.         }  
  92.     }  
  93.       
  94.         //绘制烟花  
  95.     for(var j=0;j<gloablYanhuaArray.length;j++)//烟花队列  
  96.         {     
  97.             for(var i=0;i<gloablYanhuaArray[j].yanhuaArray.length;i++)//每个烟花  
  98.             {         
  99.                 var bb = gloablYanhuaArray[j].yanhuaArray[i].color;  
  100.                 var color = bb.substring(0,bb.lastIndexOf(","))+","+gloablYanhuaArray[j].yanhuaArray[i].alpha+")";  
  101.                   
  102.                 context.fillStyle   = "rgba(255,255,255,1)";  
  103.                 context.beginPath();  
  104.                 //context.arc(gloablYanhuaArray[j].yanhuaArray[i].x,gloablYanhuaArray[j].yanhuaArray[i].y,gloablYanhuaArray[j].yanhuaArray[i].size,0,Math.PI*2,true);  
  105.                 var csize = gloablYanhuaArray[j].yanhuaArray[i].size*5;  
  106.                 //context.fillRect(gloablYanhuaArray[j].yanhuaArray[i].x-csize/2,gloablYanhuaArray[j].yanhuaArray[i].y - csize/2,gloablYanhuaArray[j].yanhuaArray[i].size,gloablYanhuaArray[j].yanhuaArray[i].size);  
  107.                 //context.drawImage(img,gloablYanhuaArray[j].yanhuaArray[i].x,gloablYanhuaArray[j].yanhuaArray[i].y,25,25);  
  108.                   
  109.                 context.drawImage(generateSprite(color,1),gloablYanhuaArray[j].yanhuaArray[i].x-csize/2,gloablYanhuaArray[j].yanhuaArray[i].y-csize/2,csize,csize);  
  110.                 context.closePath();  
  111.                 context.fill();;  
  112.                 //context.arc(yanhuaArray[i].x, yanhuaArray[i].y, yanhuaArray[i].size, 0, Math.PI * 2, true);  
  113.                 //yanhuaArray[i].dirY+=0.5;  
  114.                 gloablYanhuaArray[j].yanhuaArray[i].update();  
  115.           
  116.             }  
  117.             if(gloablYanhuaArray[j].deaded){  
  118.                 gloablYanhuaArray[j].splice(j,1);;  
  119.             }  
  120.         }  
  121.           
  122.         return canvas;  
  123. }  
  124. //生成烟花贴图  
  125. function generateSprite(colorStr,alpha) {  
  126.   
  127.     var canvas = document.createElement( 'canvas' );  
  128.     canvas.width = 5;  
  129.     canvas.height = 5;  
  130.     //var color =  colorStr.substring(0,colorStr.lastIndexOf(","))+","+alpha+")";  
  131.     var color = colorStr;  
  132.     var context = canvas.getContext( '2d' );  
  133.     var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );  
  134.     gradient.addColorStop( 0, 'rgba(255,255,255,1)' );  
  135.     gradient.addColorStop( 0.3, 'rgba(255,255,255,1)' );  
  136.     gradient.addColorStop( 0.4, color );  
  137.     gradient.addColorStop( 1, 'rgba(0,0,0,0)' );  
  138.     context.fillStyle = gradient;  
  139.     context.fillRect( 0, 0, canvas.width, canvas.height );  
  140.     return canvas;  
  141.   
  142. }   
  143. //烟花对象  
  144. function YANHUAOBJ(x,y,count,size,colormain){  
  145.   
  146.     var yanhua = new  Object();  
  147.     yanhua.x = x;  
  148.     yanhua.y = y;  
  149.     yanhua.size = size;  
  150.     yanhua.childCount = count;  
  151.     yanhua.dead = false;  
  152.     yanhua.yanhuaArray=new Array();  
  153.     yanhua.alpha = 1;  
  154.       
  155.     yanhua.r = 255;  
  156.     yanhua.g = 255;  
  157.     yanhua.b = 255;  
  158. /*  
  159.     var rand =  Math.floor(Math.random()*3);  
  160.     if(rand ==0){  
  161.         yanhua.r = Math.floor(Math.random()*255);  
  162.     }else if(rand ==1){  
  163.         yanhua.g = Math.floor(Math.random()*255);  
  164.     }else if(rand ==2){  
  165.         yanhua.b = Math.floor(Math.random()*255);  
  166.     }  
  167.     */  
  168.     yanhua.color = "rgba("+yanhua.r+","+yanhua.g+","+yanhua.b+","+yanhua.alpha+")";  
  169.     for(var i=0;i<yanhua.childCount;i++){  
  170.         yanhua.yanhuaArray.push(YANHUA(yanhua.x,yanhua.y,yanhua.size,yanhua.color,colormain));  
  171.     }  
  172.     yanhua.update = setInterval(function(){  
  173.         if(yanhua.alpha>0){  
  174.             yanhua.alpha-=0.1;  
  175.         }  
  176.         for(var j=0;j<yanhua.yanhuaArray.length;j++){  
  177.             if(yanhua.yanhuaArray[j].dead){  
  178.                 yanhua.yanhuaArray.splice(j,1);  
  179.             }  
  180.         }  
  181.         if(yanhua.yanhuaArray.length == 0){  
  182.             yanhua.dead = true;  
  183.             clearInterval(yanhua.update);  
  184.         }  
  185.     },200);  
  186.       
  187.     return yanhua;  
  188. }  
  189.  function YANHUA(x,y,size,color,colormain){  
  190.     var yanhuaObj=new Object();  
  191.     yanhuaObj.x=x,  
  192.     yanhuaObj.y=y;  
  193.     yanhuaObj.orgX=x;  
  194.     yanhuaObj.orgY=y;  
  195.     yanhuaObj.size=size;  
  196.     yanhuaObj.v = (Math.random()*10); //爆炸初速度  
  197.     yanhuaObj.a = 0.07;//爆炸加速度  
  198.     yanhuaObj.angle = Math.floor(Math.random()*360) * radis;//随机弧度  
  199.     yanhuaObj.vx = yanhuaObj.v * Math.cos(yanhuaObj.angle); //水平分速度  
  200.     yanhuaObj.vy = yanhuaObj.v * Math.sin(yanhuaObj.angle);//垂直分速度  
  201.       
  202.     yanhuaObj.dirX=(Math.random()*10-5);  
  203.     yanhuaObj.dirY=(Math.random()*10-5);  
  204.     yanhuaObj.alpha = 1;  
  205.     yanhuaObj.dead = false;  
  206.       
  207.     yanhuaObj.color = color;  
  208.     yanhuaObj.flag = false;  
  209.       
  210.     yanhuaObj.r = 255;  
  211.     yanhuaObj.g = 255;  
  212.     yanhuaObj.b = 255;  
  213.     yanhuaObj.colormain = colormain;  
  214.     var step = 10;  
  215.     var step1 = 20;  
  216.     yanhuaObj.update=function(){  
  217.             if(yanhuaObj.colormain ==0){  
  218.                 yanhuaObj.g -=step;  
  219.                 yanhuaObj.b -=step;  
  220.             }else if(yanhuaObj.colormain ==1){  
  221.                 yanhuaObj.r -=step;  
  222.                 yanhuaObj.b -=step;  
  223.             }else if(yanhuaObj.colormain ==2){  
  224.                 yanhuaObj.r -=step;  
  225.                 yanhuaObj.g -=step;  
  226.             }else if(yanhuaObj.colormain ==3){  
  227.                 var rand =  Math.floor(Math.random()*3);  
  228.                 if(rand ==0){  
  229.                     yanhuaObj.g -=step;  
  230.                     yanhuaObj.b -=step;  
  231.                 }else if(rand ==1){  
  232.                     yanhuaObj.r -=step;  
  233.                     yanhuaObj.b -=step;  
  234.                 }else if(rand ==2){  
  235.                     yanhuaObj.r -=step;  
  236.                     yanhuaObj.g -=step;  
  237.                 }  
  238.             }  
  239.               
  240.         yanhuaObj.color = "rgba("+yanhuaObj.r+","+yanhuaObj.g+","+yanhuaObj.b+","+yanhuaObj.alpha+")";  
  241.         if(yanhuaObj.size<=0){  
  242.             yanhuaObj.flag=true;  
  243.         }  
  244.         if(yanhuaObj.size>0 && !yanhuaObj.flag){  
  245.             yanhuaObj.size = yanhuaObj.size -0.5;  
  246.         }else{  
  247.             if(yanhuaObj.size<5){  
  248.                 yanhuaObj.size = yanhuaObj.size +0.4;  
  249.                 }  
  250.         }  
  251.         yanhuaObj.y+=0.4;  
  252.         if(yanhuaObj.v>=0){  
  253.             yanhuaObj.v += yanhuaObj.a-=0.02;  
  254.             yanhuaObj.vx = yanhuaObj.v * Math.cos(yanhuaObj.angle); //水平分速度  
  255.             yanhuaObj.vy = yanhuaObj.v * Math.sin(yanhuaObj.angle);//垂直分速度  
  256.             var disR=(yanhuaObj.x-yanhuaObj.orgX)*(yanhuaObj.x-yanhuaObj.orgX)+(yanhuaObj.y-yanhuaObj.orgY)*(yanhuaObj.y-yanhuaObj.orgY);  
  257.             if(disR<56000){  
  258.             //yanhuaObj.dirX=yanhuaObj.dirX*2;  
  259.             //yanhuaObj.dirY=yanhuaObj.dirY*2;  
  260.             yanhuaObj.x+=yanhuaObj.vx;  
  261.             yanhuaObj.y+=yanhuaObj.vy;  
  262.               
  263.             }else if(disR>56000){  
  264.                 yanhuaObj.x=yanhuaObj.orgX,  
  265.                 yanhuaObj.y=yanhuaObj.orgY;  
  266.                   
  267.                 yanhuaObj.UPDATE();  
  268.                 }  
  269.         }else{  
  270.             yanhuaObj.dead = true;  
  271.             if(yanhuaObj.alpha>0){  
  272.                 //yanhuaObj.alpha-=0.001;  
  273.                   
  274.             }else{  
  275.                 yanhuaObj.alpha=0;  
  276.             }  
  277.               
  278.         }  
  279.           
  280.     }  
  281.     //实现拖尾,每100毫秒产生一个尾巴  
  282.       
  283.     yanhuaObj.tail=setInterval(function(){  
  284.           
  285.         if(!yanhuaObj.dead){  
  286.             spriteArray.push(sprite(yanhuaObj.x,yanhuaObj.y,yanhuaObj.size,yanhuaObj.color));  
  287.         }else{  
  288.             clearInterval(yanhuaObj.tail);  
  289.         }  
  290.     },50);  
  291.     yanhuaObj.UPDATE = function(){  
  292.         yanhuaObj.dirX=(Math.random()*10-5);  
  293.         yanhuaObj.dirY=(Math.random()*10-5);  
  294.         yanhuaObj.r = 255;  
  295.         yanhuaObj.g = 255;  
  296.         yanhuaObj.b = 255;  
  297.   
  298.         var rand =  Math.floor(Math.random()*3);  
  299.         if(rand ==0){  
  300.             yanhuaObj.r = Math.floor(Math.random()*255);  
  301.         }else if(rand ==1){  
  302.             yanhuaObj.g = Math.floor(Math.random()*255);  
  303.         }else if(rand ==2){  
  304.             yanhuaObj.b = Math.floor(Math.random()*255);  
  305.         }  
  306.         yanhuaObj.color = "rgba("+yanhuaObj.r+","+yanhuaObj.g+","+yanhuaObj.b+","+yanhuaObj.alpha+")";  
  307.         }  
  308.       
  309.     return yanhuaObj;  
  310. }  
  311.   
  312. var mouseX;  
  313. var mouseY;  
  314. function mousemove(e){  
  315.     e=e? e:window.event;  
  316.     mouseY = e.clientY;  
  317.     mouseX = e.clientX;  
  318.   // gloablYanhuaArray.push( YANHUAOBJ(mouseX,mouseY,10,size));  
  319.     //spriteArray.push(sprite(mouseX,mouseY,50,"rgba(255,0,0,1)"));  
  320.     //console.log("gloablYanhuaArray.length:"+gloablYanhuaArray.length);  
  321.     //draw();  
  322. }  
  323. function mousedown(e){  
  324.     e=e? e:window.event;  
  325.     mouseY = e.clientY;  
  326.     mouseX = e.clientX;  
  327.     gloablYanhuaArray.push( YANHUAOBJ(mouseX,mouseY,50,size));  
  328. }  
  329. function explod(){  
  330.     var border = 300;  
  331.     var x = Math.random()*(screeWidth);   
  332.     var y = Math.random()*(screeHeight);  
  333.     var colormain =  Math.floor(Math.random()*4);  
  334.     gloablYanhuaArray.push( YANHUAOBJ(x,y,50,size,colormain));  
  335. }  
  336. function sprite(x,y,size,color){  
  337.     var sprite=new Object();  
  338.     sprite.g=5;  
  339.     sprite.x=x,  
  340.     sprite.y=y;  
  341.     sprite.orgX=x;  
  342.     sprite.orgY=y;  
  343.     sprite.size=size;  
  344.     sprite.color = color;  
  345.     sprite.deaded = false;  
  346.     sprite.alpha = 1;  
  347.     sprite.r = 255;  
  348.     sprite.g = 255;  
  349.     sprite.b = 255;  
  350.     var rand =  Math.floor(Math.random()*3);  
  351.       
  352.   
  353.       
  354.     sprite.dead=setInterval(function(){  
  355.         sprite.alpha = sprite.alpha-0.06;  
  356.         sprite.size = sprite.size - 0.1;  
  357.         sprite.alpha = sprite.alpha.toFixed(1);  
  358.         if(sprite.alpha == 0){  
  359.             sprite.deaded =true;  
  360.             //console.log(sprite.deaded);  
  361.             clearInterval(sprite.dead);  
  362.         }  
  363.     },120);  
  364.       
  365.     return sprite;;  
  366. }  
  367. </script>  
  368.   
  369. </head>  
  370. <body style="background-color:#fff;">  
  371. <img id="tulip" src="lizi1.png" alt="The Tulip" style="display:none;" />  
  372. <canvas id="myCanvas"  style="background:rgba(0, 0, 0, 1);" onmousemove="mousemove();" onmousedown="mousedown();">  
  373. Your browser does not support the HTML5 canvas tag.  
  374. </canvas>  
  375. </body>  
  376. </html> 

猜你喜欢

转载自blog.csdn.net/qq_37838223/article/details/80499285