canvas焰火特效
canvas焰火特效
之前在抖音上看到了一个很漂亮的焰火效果。这会儿有时间就用canvas实现了一下。
演示地址:http://suohb.com/work/firework4.htm
先看效果:(静态图片看不太出效果,请直接查看演示地址,考验电脑CPU的时候到了)
实现原理:
焰火特效运用到的物理知识就是抛物线运动。
看起来很复杂的焰火实际上就是一条条的抛物线。
从一个中心点向四周方向抛出一个质点。将质点的轨迹画出来,就是焰火效果了。
//每一个质点对象
1 var obj = { 2 x: x,//当前X坐标 3 y: y,//当前Y坐标 4 sx: Math.cos(deg)*curSpeed,//X轴方向速度 5 sy: Math.sin(deg)*curSpeed,//Y轴方向速度 6 len: len + level*10*Math.random(),//焰火显示长度(这么多质点连接起来) 7 limit: limit + level*10*Math.random(),//质点移动最大步数 8 color: color,//焰火颜色 9 level: level,//焰火等级(因为特效是二级焰火,可以做多级) 10 list:[{x:x,y:y}]//质点轨迹(将这些轨迹连起来就是焰火的其中一条线) 11 };
//向360度方向生成一批质点,形成一个焰火元素
1 function addFire(x,y,color,level){ 2 curLevel = level ; 3 var lineLen = 10+level*20 + Math.random()*10, 4 deg , 5 speed = 1 + Math.random()*level*.4 , 6 len = 15 + Math.random()*level*6, 7 limit = len + 4 + Math.random()*level; 8 for(var i = 0 ; i < lineLen ; i ++){ 9 deg = i*(Math.PI*2/lineLen)+Math.random() ; 10 var curSpeed = speed + Math.random(); 11 var obj = 质点对象 12 list.push(obj); 13 } 14 }
//更新质点位置,并将新位置插入质点轨迹之中
1 function reviewFire(){ 2 for(var i = 0 ; i <list.length ; i++){ 3 let obj = list[i]; 4 obj.x += obj.sx ; 5 obj.y += obj.sy ; 6 obj.sy += G ;//抛物运动中的重力加速度 7 obj.list.push({x:obj.x,y:obj.y}); 8 obj.list = obj.list.slice(-obj.len); 9 } 10 }
//画出轨迹即可
1 function drawFire(){ 2 cxt.clearRect(0,0,pageWidth,pageHeight); 3 var obj ; 4 for(var i = 0 ; i < list.length ; i ++){ 5 obj = list[i] ; 6 cxt.beginPath(); 7 for(var j = 0 ; j < obj.list.length ; j++){ 8 if(i == 0) 9 cxt.moveTo(obj.list[j].x ,obj.list[j].y); 10 else{ 11 cxt.lineTo(obj.list[j].x ,obj.list[j].y); 12 } 13 } 14 cxt.strokeStyle = obj.color ; 15 cxt.lineWidth = obj.level ; 16 cxt.stroke(); 17 } 18 }
完整代码:
1 <!doctype html> 2 <html> 3 <head> 4 <meta http-equiv="Pragma" content="no-cache" /> 5 <meta http-equiv="Cache-Control" content="no-cache" /> 6 <meta http-equiv="Expires" content="0" /> 7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 8 <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" /> 9 <title>焰火特效-长按二维码关注公众号,了解更多特效</title> 10 <style type="text/css"> 11 html{ 12 height: 100%; 13 } 14 html,body,ul,li,canvas{ 15 margin: 0; 16 padding: 0; 17 } 18 19 </style> 20 </head> 21 <body bgcolor="#000000"> 22 <canvas id="knife"></canvas> 23 <img src="../images/qr.jpg" style="position:fixed;bottom:0;width:100px;height:100px;right:0;"> 24 </body> 25 <script> 26 var canvas = document.getElementById("knife"); 27 canvas.style.position = "absolute" ; 28 canvas.style.top = 0 ; 29 var pageWidth = window.innerWidth ; 30 var pageHeight = window.innerHeight ; 31 canvas.width = window.innerWidth ; 32 canvas.height = window.innerHeight ; 33 var cxt = canvas.getContext("2d"); 34 var list = [] ; 35 var G = 0.036 ; 36 var colors = ["#8b008b","#ff69b4","#7fff00","#1e90ff","#00bfff","#0FF","#7cfc00","#ffd700","#ffdead","#f00"]; 37 var curLevel = 0 ; 38 var curColor = 0 ; 39 40 function addFire(x,y,color,level){ 41 curLevel = level ; 42 var lineLen = 10+level*20 + Math.random()*10, 43 deg , 44 speed = 1 + Math.random()*level*.4 , 45 len = 15 + Math.random()*level*6, 46 limit = len + 4 + Math.random()*level; 47 for(var i = 0 ; i < lineLen ; i ++){ 48 deg = i*(Math.PI*2/lineLen)+Math.random() ; 49 var curSpeed = speed + Math.random(); 50 var obj = { 51 x: x, 52 y: y, 53 sx: Math.cos(deg)*curSpeed, 54 sy: Math.sin(deg)*curSpeed, 55 len: len + level*10*Math.random(), 56 limit: limit + level*10*Math.random(), 57 color: color, 58 level: level, 59 list:[{x:x,y:y}] 60 }; 61 list.push(obj); 62 } 63 } 64 function reviewFire(){ 65 for(var i = 0 ; i <list.length ; i++){ 66 let obj = list[i]; 67 obj.x += obj.sx ; 68 obj.y += obj.sy ; 69 obj.sy += G ; 70 obj.list.push({x:obj.x,y:obj.y}); 71 obj.list = obj.list.slice(-obj.len); 72 } 73 } 74 function drawFire(){ 75 cxt.clearRect(0,0,pageWidth,pageHeight); 76 var obj ; 77 for(var i = 0 ; i < list.length ; i ++){ 78 obj = list[i] ; 79 cxt.beginPath(); 80 for(var j = 0 ; j < obj.list.length ; j++){ 81 if(i == 0) 82 cxt.moveTo(obj.list[j].x ,obj.list[j].y); 83 else{ 84 cxt.lineTo(obj.list[j].x ,obj.list[j].y); 85 } 86 } 87 cxt.strokeStyle = obj.color ; 88 cxt.lineWidth = obj.level ; 89 cxt.stroke(); 90 } 91 } 92 function step(){ 93 if(curLevel == 1 && list.length == 0){ 94 addFire(pageWidth/2,100,colors[curColor ++ % colors.length],2); 95 } 96 reviewFire(); 97 drawFire(); 98 requestAnimationFrame(step) 99 } 100 requestAnimationFrame(step) 101 addFire(pageWidth/2,100,colors[curColor ++ % colors.length],2); 102 </script> 103 </html>
了解更多特效,请关注我的微信公众号:
版权声明:本文为shb190802原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。