首页 > 代码库 > 烟花效果(Canvas和Proton)
烟花效果(Canvas和Proton)
最近看了很多的烟花效果,我自己的感觉就是代码不是很难,只是需要对它的原理好好理解一下。我们都知道一个烟花从发射到炸裂经过的几个阶段,以及这些过程中涉及到了那些东西。那些量会对最后的炸开效果有影响,我们首相应该把这些量考虑好,之后才能上手去写这个程序,我不知道第一个人是怎么写出的但是我看出基本上所有的烟花效果都是那几个量,没什么区别只是有一些具体的值的大小可能不一样。下面我就分享一下我从网上找的一段代码:
这个烟花效果是自动随机产生烟花,不是我们控制的,相对比较简单。
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>Canvas烟花</title> 7 <meta name="description" content=""> 8 <meta name="keywords" content=""> 9 <link href="" rel="stylesheet"> 10 <style type="text/css"> 11 body { 12 padding: 0; 13 margin: 0; 14 background: #000; 15 } 16 </style> 17 </head> 18 19 <body> 20 <canvas id="canvas">Canvas is not supported in your browser.</canvas> 21 <script type="text/javascript"> 22 window.requestAnimationFrame = (function() { 23 return window.requestAnimationFrame || 24 window.webkitRequestAnimationFrame || 25 window.mozRequestAnimationFrame || 26 function(callback) { 27 window.setTimeout(callback, 1000 / 60); //每秒60帧 28 } 29 })(); 30 31 var canvas = document.getElementById("canvas"), 32 ctx = canvas.getContext("2d"), 33 cw = window.innerWidth, 34 ch = window.innerHeight, 35 fireworks = [], //烟花数组 36 particles = [], //烟花爆炸屑数字 37 hue = 120, //初始色调0/360 红色 120 绿色240 蓝色 38 timerTotal = 80, //每隔80下释放一次烟花 39 timerTick = 0; 40 41 canvas.width = cw; 42 canvas.height = ch; 43 44 // 生成随机数 45 function random(min, max) { 46 return Math.random() * (max - min) + min; 47 } 48 // 计算点(sx,sy)到点(tx,ty)之间的距离 49 function caculateDistance(sx, sy, tx, ty) { 50 var xDistance = sx - tx, 51 yDistance = sy - ty; 52 return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2)); 53 } 54 // 烟花对象(sx,sy)初始位置(tx,ty)目标位置 55 function Firework(sx, sy, tx, ty) { 56 this.x = sx; //实时运行坐标x 57 this.y = sy; //实时运行坐标y 58 this.sx = sx; //初始位置坐标x 59 this.sy = sy; //初始位置坐标y 60 this.tx = tx; //目标位置坐标x 61 this.ty = ty; //目标位置坐标y 62 this.distanceToTarget = caculateDistance(sx, sy, tx, ty); //计算初始位置到目标位置之间的距离 63 this.distanceTraveled = 0; //已运行距离 64 this.coordinates = []; //这是一个辅助变量,用于生成实时运行轨迹 65 this.coordinatesCount = 3; 66 while (this.coordinatesCount--) { 67 this.coordinates.push([this.x, this.y]); 68 } 69 this.angle = Math.atan2(ty - sy, tx - sx); //初始位置和目标位置之间的角度 70 this.speed = 2; //初始速度 71 this.acceleration = 1.05 //加速度 72 this.brightness = random(50, 70); //明度 73 this.targetRadius = 1; //目标位置标示圆圈的初始半径 74 } 75 // 更新烟花的位置 76 Firework.prototype.update = function(index) { 77 this.coordinates.pop(); 78 this.coordinates.unshift([this.x, this.y]); 79 // 上面是一个技巧吧 先将数组最后一个移除,然后将当前烟花位置插入到第一个,那数组最后一个坐标和更新之后的坐标之间就形成了一条轨迹 80 // 让目标标示处圆圈动起来 81 if (this.targetRadius < 8) { 82 this.targetRadius += 0.3; 83 } else { 84 this.targetRadius = 1; 85 } 86 this.speed *= this.acceleration; //根据加速度变换速度 87 var vx = Math.cos(this.angle) * this.speed, //计算水平方向速度 88 vy = Math.sin(this.angle) * this.speed; //计算垂直方向速度 89 this.distanceTraveled = caculateDistance(this.sx, this.sy, this.x + vx, this.y + vy); //重新计算烟花已运行的距离 90 // 如果烟花运行距离大于或等于初始位置到目标之间的距离,生成新烟花并移除当前烟花,否则更新烟花位置 91 if (this.distanceTraveled >= this.distanceToTarget) { 92 createParticles(this.tx, this.ty); 93 fireworks.splice(index, 1); 94 } else { 95 this.x += vx; 96 this.y += vy; 97 } 98 } 99 100 Firework.prototype.draw = function() { 101 // 画出烟花运行轨迹 102 ctx.beginPath(); 103 ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]); 104 ctx.lineTo(this.x, this.y); 105 ctx.strokeStyle = ‘hsl(‘ + hue + ‘,100%,‘ + this.brightness + ‘%)‘; 106 ctx.stroke(); 107 // 画出目标位置的小圆圈 108 ctx.beginPath(); 109 ctx.arc(this.tx, this.ty, this.targetRadius, 0, Math.PI * 2); 110 ctx.stroke(); 111 } 112 // 烟花爆炸屑对象 113 function Particle(x, y) { 114 this.x = x; 115 this.y = y; 116 this.coordinates = []; 117 this.coordinatesCount = 5; 118 while (this.coordinatesCount--) { 119 this.coordinates.push([this.x, this.y]); 120 } 121 this.angle = random(0, 2 * Math.PI); //生成任意方向的碎屑 122 this.speed = random(1, 10); //随机速度 123 this.friction = 0.95 //摩擦力 124 this.gravity = 1; //重力 125 this.hue = random(hue - 20, hue + 20); //生成与烟花色彩相近的碎屑 126 this.brightness = random(50, 80); //随机明度 127 this.alpha = 1; //初始透明度 128 this.decay = random(0.015, 0.03); //碎屑小时的时间 129 } 130 131 Particle.prototype.update = function(index) { 132 this.coordinates.pop(); 133 this.coordinates.unshift([this.x, this.y]); 134 // 上面是一个技巧吧,先将数组最后一个移除,然后将当前烟花位置插入到第一个,那数组最后一个 135 // 元素和更新之后的坐标就形成了一条轨迹 136 this.speed *= this.friction; 137 this.x += Math.cos(this.angle) * this.speed; 138 this.y += Math.sin(this.angle) * this.speed + this.gravity; 139 this.alpha -= this.decay; 140 if (this.alpha <= this.decay) { 141 particles.splice(index, 1); 142 } 143 } 144 145 Particle.prototype.draw = function() { 146 ctx.beginPath(); 147 ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]); 148 ctx.lineTo(this.x, this.y); 149 ctx.strokeStyle = ‘hsla(‘ + this.hue + ‘,100%,‘ + this.brightness + ‘%,‘ + this.alpha + ‘)‘; 150 ctx.stroke(); 151 } 152 153 function createParticles(x, y) { 154 // 生成30个烟花碎屑 155 var particleCount = 30; 156 while (particleCount--) { 157 particles.push(new Particle(x, y)); 158 } 159 } 160 161 function loop() { 162 // 流畅的动画过程 163 requestAnimationFrame(loop); 164 hue += 0.5; 165 ctx.globalCompositeOperation = ‘destination-out‘; 166 ctx.fillStyle = ‘rgba(0, 0, 0, 0.5)‘; 167 ctx.fillRect(0, 0, cw, ch); 168 ctx.globalCompositeOperation = ‘lighter‘; 169 var i = fireworks.length; 170 while (i--) { 171 fireworks[i].draw(); 172 fireworks[i].update(i); 173 } 174 var i = particles.length; 175 while (i--) { 176 particles[i].draw(); 177 particles[i].update(i); 178 } 179 if (timerTick >= timerTotal) { 180 fireworks.push(new Firework(cw / 2, ch, random(0, cw), random(0, ch / 2))); 181 timerTick = 0; 182 } else { 183 timerTick++; 184 } 185 } 186 window.onload = loop; 187 </script> 188 </body> 189 190 </html>
下面还有一段代码也是一个烟花效果,不过这个是一个更加完善的烟花效果,它是我们鼠标点击哪里哪里就产生烟花。
1 <!DOCTYPE html> 2 <!-- saved from url=http://keyup.cn --> 3 <html> 4 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 8 <meta content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"> 9 10 <meta name="apple-mobile-web-app-capable" content="yes"> 11 12 <meta name="apple-mobile-web-app-status-bar-style" content="black"> 13 14 <title>放烟花喽-前端开发知识</title> 15 16 <style type="text/css"> 17 html, 18 body { 19 height: 100%; 20 margin: 0; 21 padding: 0 22 } 23 24 ul, 25 li { 26 text-indent: 0; 27 text-decoration: none; 28 margin: 0; 29 padding: 0 30 } 31 32 img { 33 border: 0 34 } 35 36 body { 37 background-color: #000; 38 color: #999; 39 font: 100%/18px helvetica, arial, sans-serif 40 } 41 42 canvas { 43 cursor: crosshair; 44 display: block; 45 left: 0; 46 position: absolute; 47 top: 0; 48 z-index: 20 49 } 50 51 #header img { 52 width: 100%; 53 height: 20%; 54 } 55 56 #bg img { 57 width: 100%; 58 height: 80%; 59 } 60 61 #header, 62 #bg { 63 position: fixed; 64 left: 0; 65 right: 0; 66 z-index: 10 67 } 68 69 #header { 70 top: 0 71 } 72 73 #bg { 74 position: fixed; 75 z-index: 1; 76 } 77 78 audio { 79 position: fixed; 80 display: none; 81 bottom: 0; 82 left: 0; 83 right: 0; 84 width: 100%; 85 z-index: 5 86 } 87 </style> 88 89 <!-- <link rel="shortcut icon" type="image/x-icon" href=""> --> 90 91 <style type="text/css"></style> 92 <style id="style-1-cropbar-clipper"> 93 .en-markup-crop-options { 94 top: 18px !important; 95 left: 50% !important; 96 margin-left: -100px !important; 97 width: 200px !important; 98 border: 2px rgba(255, 255, 255, .38) solid !important; 99 border-radius: 4px !important; 100 } 101 102 .en-markup-crop-options div div:first-of-type { 103 margin-left: 0px !important; 104 } 105 </style> 106 </head> 107 108 <body> 109 <div id="bg"><img id="bgimg" src="a1.jpg"></div> 110 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> 111 <script type="text/javascript"> 112 $(function() { 113 var Fireworks = function() { 114 var self = this; 115 var rand = function(rMi, rMa) { 116 return ~~((Math.random() * (rMa - rMi + 1)) + rMi); 117 } 118 var hitTest = function(x1, y1, w1, h1, x2, y2, w2, h2) { 119 return !(x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1); 120 }; 121 window.requestAnimFrame = function() { 122 return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(a) { 123 window.setTimeout(a, 1E3 / 60) 124 } 125 }(); 126 127 self.init = function() { 128 self.canvas = document.createElement(‘canvas‘); 129 // cw:画布的宽 ch:画布的高 130 self.canvas.width = self.cw = $(window).innerWidth(); 131 self.canvas.height = self.ch = $(window).innerHeight(); 132 // 自身的粒子 133 self.particles = [];//烟花爆炸屑的数字 134 self.partCount = 250;//烟花的数量 135 self.fireworks = []; //烟花数组 136 self.mx = self.cw / 2; 137 self.my = self.ch / 2; 138 self.currentHue = 30;// 当前色调 139 self.partSpeed = 5; // 烟花散开的速度 140 self.partSpeedVariance = 10; // 加速度 141 self.partWind = 50; // 烟花散开之后的一个曲线值 142 self.partFriction = 5; // 摩擦力 143 self.partGravity = 1; // 重力 144 self.hueMin = 0; // 最小色调 145 self.hueMax = 360; // 最大色调 146 self.fworkSpeed = 4; // 烟花子弹的速度 147 self.fworkAccel = 10; //烟花子弹加速度 148 self.hueVariance = 80; //色调的多样性 149 self.flickerDensity = 25; //闪光密度 150 self.showShockwave = true; // 151 self.showTarget = false; // 152 self.clearAlpha = 25; //阿尔法通道值即透明度值 153 154 // 设置画板的一些参数 155 $(document.body).append(self.canvas); 156 self.ctx = self.canvas.getContext(‘2d‘); 157 self.ctx.lineCap = ‘round‘; 158 self.ctx.lineJoin = ‘round‘; 159 self.lineWidth = 1; 160 self.bindEvents(); 161 self.canvasLoop(); 162 163 self.canvas.onselectstart = function() { 164 return false; 165 }; 166 }; 167 // 创建烟花炸屑 168 self.createParticles = function(x, y, hue) { 169 var countdown = self.partCount; 170 while (countdown--) { 171 var newParticle = { 172 x: x, 173 y: y, 174 coordLast: [{ 175 x: x, 176 y: y 177 }, { 178 x: x, 179 y: y 180 }, { 181 x: x, 182 y: y 183 }], 184 // 角度 185 angle: rand(0, 360), 186 // 速度 187 speed: rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance)), 188 // 摩擦力 189 friction: 1 - self.partFriction / 100, 190 // 重力 191 gravity: self.partGravity / 2, 192 // 色调 193 hue: rand(hue - self.hueVariance, hue + self.hueVariance), 194 // 明亮度 195 brightness: rand(50, 80), 196 // 加速度 197 alpha: rand(40, 100) / 100, 198 // 衰退 199 decay: rand(10, 50) / 1000, 200 // 弯曲度 201 wind: (rand(0, self.partWind) - (self.partWind / 2)) / 25, 202 // 线宽 203 lineWidth: self.lineWidth 204 }; 205 self.particles.push(newParticle); 206 } 207 }; 208 209 // 上升的烟花弹 210 self.updateParticles = function() { 211 var i = self.particles.length; 212 while (i--) { 213 var p = self.particles[i]; 214 // 定义弧度 215 var radians = p.angle * Math.PI / 180; 216 // x轴速度 217 var vx = Math.cos(radians) * p.speed; 218 // y轴速度 219 var vy = Math.sin(radians) * p.speed; 220 // 速度等于自身乘上摩擦力 221 p.speed *= p.friction; 222 223 // 我不是很理解这一段尤其是coordLast希望懂得人能给解释一下 224 p.coordLast[2].x = p.coordLast[1].x; 225 p.coordLast[2].y = p.coordLast[1].y; 226 p.coordLast[1].x = p.coordLast[0].x; 227 p.coordLast[1].y = p.coordLast[0].y; 228 p.coordLast[0].x = p.x; 229 p.coordLast[0].y = p.y; 230 231 // 这里主要是坐标的变化 232 p.x += vx; 233 p.y += vy; 234 p.y += p.gravity; 235 236 // 这里主要是角度的变化公式和透明度的改变 237 p.angle += p.wind; 238 p.alpha -= p.decay; 239 // hitTest 碰撞检测 240 if (!hitTest(0, 0, self.cw, self.ch, p.x - p.radius, p.y - p.radius, p.radius * 2, p.radius * 2) || p.alpha < .05) { 241 self.particles.splice(i, 1); 242 } 243 }; 244 }; 245 246 self.drawParticles = function() { 247 var i = self.particles.length; 248 while (i--) { 249 var p = self.particles[i]; 250 251 var coordRand = (rand(1, 3) - 1); 252 self.ctx.beginPath(); 253 self.ctx.moveTo(Math.round(p.coordLast[coordRand].x), Math.round(p.coordLast[coordRand].y)); 254 self.ctx.lineTo(Math.round(p.x), Math.round(p.y)); 255 self.ctx.closePath(); 256 self.ctx.strokeStyle = ‘hsla(‘ + p.hue + ‘, 100%, ‘ + p.brightness + ‘%, ‘ + p.alpha + ‘)‘; 257 self.ctx.stroke(); 258 259 if (self.flickerDensity > 0) { 260 var inverseDensity = 50 - self.flickerDensity; 261 if (rand(0, inverseDensity) === inverseDensity) { 262 self.ctx.beginPath(); 263 self.ctx.arc(Math.round(p.x), Math.round(p.y), rand(p.lineWidth, p.lineWidth + 3) / 2, 0, Math.PI * 2, false) 264 self.ctx.closePath(); 265 var randAlpha = rand(50, 100) / 100; 266 self.ctx.fillStyle = ‘hsla(‘ + p.hue + ‘, 100%, ‘ + p.brightness + ‘%, ‘ + randAlpha + ‘)‘; 267 self.ctx.fill(); 268 } 269 } 270 }; 271 }; 272 273 274 self.createFireworks = function(startX, startY, targetX, targetY) { 275 var newFirework = { 276 x: startX, 277 y: startY, 278 startX: startX, 279 startY: startY, 280 hitX: false, 281 hitY: false, 282 coordLast: [{ 283 x: startX, 284 y: startY 285 }, { 286 x: startX, 287 y: startY 288 }, { 289 x: startX, 290 y: startY 291 }], 292 targetX: targetX, 293 targetY: targetY, 294 speed: self.fworkSpeed, 295 angle: Math.atan2(targetY - startY, targetX - startX), 296 shockwaveAngle: Math.atan2(targetY - startY, targetX - startX) + (90 * (Math.PI / 180)), 297 acceleration: self.fworkAccel / 100, 298 hue: self.currentHue, 299 brightness: rand(50, 80), 300 alpha: rand(50, 100) / 100, 301 lineWidth: self.lineWidth 302 }; 303 self.fireworks.push(newFirework); 304 305 }; 306 307 308 self.updateFireworks = function() { 309 var i = self.fireworks.length; 310 311 while (i--) { 312 var f = self.fireworks[i]; 313 self.ctx.lineWidth = f.lineWidth; 314 315 vx = Math.cos(f.angle) * f.speed, 316 vy = Math.sin(f.angle) * f.speed; 317 f.speed *= 1 + f.acceleration; 318 f.coordLast[2].x = f.coordLast[1].x; 319 f.coordLast[2].y = f.coordLast[1].y; 320 f.coordLast[1].x = f.coordLast[0].x; 321 f.coordLast[1].y = f.coordLast[0].y; 322 f.coordLast[0].x = f.x; 323 f.coordLast[0].y = f.y; 324 325 if (f.startX >= f.targetX) { 326 if (f.x + vx <= f.targetX) { 327 f.x = f.targetX; 328 f.hitX = true; 329 } else { 330 f.x += vx; 331 } 332 } else { 333 if (f.x + vx >= f.targetX) { 334 f.x = f.targetX; 335 f.hitX = true; 336 } else { 337 f.x += vx; 338 } 339 } 340 341 if (f.startY >= f.targetY) { 342 if (f.y + vy <= f.targetY) { 343 f.y = f.targetY; 344 f.hitY = true; 345 } else { 346 f.y += vy; 347 } 348 } else { 349 if (f.y + vy >= f.targetY) { 350 f.y = f.targetY; 351 f.hitY = true; 352 } else { 353 f.y += vy; 354 } 355 } 356 357 if (f.hitX && f.hitY) { 358 self.createParticles(f.targetX, f.targetY, f.hue); 359 self.fireworks.splice(i, 1); 360 361 } 362 }; 363 }; 364 365 self.drawFireworks = function() { 366 var i = self.fireworks.length; 367 self.ctx.globalCompositeOperation = ‘lighter‘; 368 while (i--) { 369 var f = self.fireworks[i]; 370 self.ctx.lineWidth = f.lineWidth; 371 372 var coordRand = (rand(1, 3) - 1); 373 self.ctx.beginPath(); 374 self.ctx.moveTo(Math.round(f.coordLast[coordRand].x), Math.round(f.coordLast[coordRand].y)); 375 self.ctx.lineTo(Math.round(f.x), Math.round(f.y)); 376 self.ctx.closePath(); 377 self.ctx.strokeStyle = ‘hsla(‘ + f.hue + ‘, 100%, ‘ + f.brightness + ‘%, ‘ + f.alpha + ‘)‘; 378 self.ctx.stroke(); 379 380 if (self.showTarget) { 381 self.ctx.save(); 382 self.ctx.beginPath(); 383 self.ctx.arc(Math.round(f.targetX), Math.round(f.targetY), rand(1, 8), 0, Math.PI * 2, false) 384 self.ctx.closePath(); 385 self.ctx.lineWidth = 1; 386 self.ctx.stroke(); 387 self.ctx.restore(); 388 } 389 390 if (self.showShockwave) { 391 self.ctx.save(); 392 self.ctx.translate(Math.round(f.x), Math.round(f.y)); 393 self.ctx.rotate(f.shockwaveAngle); 394 self.ctx.beginPath(); 395 self.ctx.arc(0, 0, 1 * (f.speed / 5), 0, Math.PI, true); 396 self.ctx.strokeStyle = ‘hsla(‘ + f.hue + ‘, 100%, ‘ + f.brightness + ‘%, ‘ + rand(25, 60) / 100 + ‘)‘; 397 self.ctx.lineWidth = f.lineWidth; 398 self.ctx.stroke(); 399 self.ctx.restore(); 400 } 401 }; 402 }; 403 404 self.bindEvents = function() { 405 $(window).on(‘resize‘, function() { 406 clearTimeout(self.timeout); 407 self.timeout = setTimeout(function() { 408 self.canvas.width = self.cw = $(window).innerWidth(); 409 self.canvas.height = self.ch = $(window).innerHeight(); 410 self.ctx.lineCap = ‘round‘; 411 self.ctx.lineJoin = ‘round‘; 412 }, 100); 413 }); 414 415 $(self.canvas).on(‘mousedown‘, function(e) { 416 self.mx = e.pageX - self.canvas.offsetLeft; 417 self.my = e.pageY - self.canvas.offsetTop; 418 self.currentHue = rand(self.hueMin, self.hueMax); 419 self.createFireworks(self.cw / 2, self.ch, self.mx, self.my); 420 421 $(self.canvas).on(‘mousemove.fireworks‘, function(e) { 422 self.mx = e.pageX - self.canvas.offsetLeft; 423 self.my = e.pageY - self.canvas.offsetTop; 424 self.currentHue = rand(self.hueMin, self.hueMax); 425 self.createFireworks(self.cw / 2, self.ch, self.mx, self.my); 426 }); 427 }); 428 429 $(self.canvas).on(‘mouseup‘, function(e) { 430 $(self.canvas).off(‘mousemove.fireworks‘); 431 }); 432 433 } 434 435 self.clear = function() { 436 self.particles = []; 437 self.fireworks = []; 438 self.ctx.clearRect(0, 0, self.cw, self.ch); 439 }; 440 441 442 self.canvasLoop = function() { 443 requestAnimFrame(self.canvasLoop, self.canvas); 444 self.ctx.globalCompositeOperation = ‘destination-out‘; 445 self.ctx.fillStyle = ‘rgba(0,0,0,‘ + self.clearAlpha / 100 + ‘)‘; 446 self.ctx.fillRect(0, 0, self.cw, self.ch); 447 self.updateFireworks(); 448 self.updateParticles(); 449 self.drawFireworks(); 450 self.drawParticles(); 451 452 }; 453 454 self.init(); 455 456 } 457 var fworks = new Fireworks(); 458 459 }); 460 </script> 461 <script type="text/javascript"> 462 $(document).ready(function() { 463 setTimeout(function() { 464 $("#header").hide("slow"); 465 }, 2000); 466 }); 467 </script> 468 </body> 469 470 </html>
这个烟花效果更加好一些,并且我们可以通过修改function init()里边的值来调整最后的效果,我改了一些最后产生了很炫的效果,你们可以试试。我们还可以将这些值换成变量,我们可以弄几个input通过value来传我们具体的值这样我们就能很随意的看我们想看的效果。这个我这里就不试了。
下面是一个插件实现的烟花效果:
下面我主要是推荐一个HTML5的粒子引擎,它就是Proton粒子引擎,官网:http://a-jie.github.io/Proton/,里边有很多的效果,这是它里边的烟花效果:http://a-jie.github.io/Proton/example/sparks/firework/fireworks.html,基本的代码如下:
1 <!DOCTYPE HTML> 2 <html> 3 4 <head> 5 <title>proton.js-game-fireworks</title> 6 <meta charset="utf-8"> 7 <style type="text/css"> 8 body { 9 font-family: Monospace; 10 background-color: #f0f0f0; 11 margin: 0px; 12 overflow: hidden; 13 } 14 15 #testCanvas { 16 background: #000000; 17 } 18 </style> 19 </head> 20 21 <body> 22 <canvas id="testCanvas"></canvas> 23 <script src="stats.min.js"></script> 24 <script src="proton-2.1.0.min.js"></script> 25 <script> 26 var canvas; 27 var context; 28 var proton; 29 var renderer; 30 var emitter; 31 var stats; 32 33 Main(); 34 35 function Main() { 36 canvas = document.getElementById("testCanvas"); 37 canvas.width = window.innerWidth; 38 canvas.height = window.innerHeight; 39 context = canvas.getContext(‘2d‘); 40 //context.globalCompositeOperation = "lighter"; 41 addStats(); 42 43 createProton(); 44 tick(); 45 } 46 47 function addStats() { 48 stats = new Stats(); 49 stats.setMode(2); 50 stats.domElement.style.position = ‘absolute‘; 51 stats.domElement.style.left = ‘0px‘; 52 stats.domElement.style.top = ‘0px‘; 53 document.body.appendChild(stats.domElement); 54 } 55 56 function createProton(image) { 57 proton = new Proton; 58 emitter = new Proton.Emitter(); 59 emitter.rate = new Proton.Rate(new Proton.Span(1, 3), 1); 60 emitter.addInitialize(new Proton.Mass(1)); 61 emitter.addInitialize(new Proton.Radius(2, 4)); 62 emitter.addInitialize(new Proton.P(new Proton.LineZone(10, canvas.height, canvas.width - 10, canvas.height))); 63 emitter.addInitialize(new Proton.Life(1, 1.5)); 64 emitter.addInitialize(new Proton.V(new Proton.Span(4, 6), new Proton.Span(0, 0, true), ‘polar‘)); 65 emitter.addBehaviour(new Proton.Gravity(1)); 66 emitter.addBehaviour(new Proton.Color(‘#ff0000‘, ‘random‘)); 67 emitter.emit(); 68 proton.addEmitter(emitter); 69 70 renderer = new Proton.Renderer(‘canvas‘, proton, canvas); 71 renderer.onProtonUpdate = function() { 72 context.fillStyle = "rgba(0, 0, 0, 0.1)"; 73 context.fillRect(0, 0, canvas.width, canvas.height); 74 }; 75 renderer.start(); 76 77 ////NOTICE :you can only use two emitters do this effect.In this demo I use more emitters want to test the emtter‘s life 78 emitter.addEventListener(Proton.PARTICLE_DEAD, function(particle) { 79 if (Math.random() < .7) 80 createFirstEmitter(particle); 81 else 82 createSecendEmitter(particle); 83 }); 84 } 85 86 function createFirstEmitter(particle) { 87 var subemitter = new Proton.Emitter(); 88 subemitter.rate = new Proton.Rate(new Proton.Span(250, 300), 1); 89 subemitter.addInitialize(new Proton.Mass(1)); 90 subemitter.addInitialize(new Proton.Radius(1, 2)); 91 subemitter.addInitialize(new Proton.Life(1, 3)); 92 subemitter.addInitialize(new Proton.V(new Proton.Span(2, 4), new Proton.Span(0, 360), ‘polar‘)); 93 subemitter.addBehaviour(new Proton.RandomDrift(10, 10, .05)); 94 subemitter.addBehaviour(new Proton.Alpha(1, 0)); 95 subemitter.addBehaviour(new Proton.Gravity(3)); 96 var color = Math.random() > .3 ? Proton.MathUtils.randomColor() : ‘random‘; 97 subemitter.addBehaviour(new Proton.Color(color)); 98 subemitter.p.x = particle.p.x; 99 subemitter.p.y = particle.p.y; 100 subemitter.emit(‘once‘, true); 101 proton.addEmitter(subemitter); 102 } 103 104 function createSecendEmitter(particle) { 105 var subemitter = new Proton.Emitter(); 106 subemitter.rate = new Proton.Rate(new Proton.Span(100, 120), 1); 107 subemitter.addInitialize(new Proton.Mass(1)); 108 subemitter.addInitialize(new Proton.Radius(4, 8)); 109 subemitter.addInitialize(new Proton.Life(1, 2)); 110 subemitter.addInitialize(new Proton.V([1, 2], new Proton.Span(0, 360), ‘polar‘)); 111 subemitter.addBehaviour(new Proton.Alpha(1, 0)); 112 subemitter.addBehaviour(new Proton.Scale(1, .1)); 113 subemitter.addBehaviour(new Proton.Gravity(1)); 114 var color = Proton.MathUtils.randomColor(); 115 subemitter.addBehaviour(new Proton.Color(color)); 116 subemitter.p.x = particle.p.x; 117 subemitter.p.y = particle.p.y; 118 subemitter.emit(‘once‘, true); 119 proton.addEmitter(subemitter); 120 } 121 122 function tick() { 123 requestAnimationFrame(tick); 124 125 stats.begin(); 126 proton.update(); 127 stats.end(); 128 } 129 </script> 130 </body> 131 132 </html>
这里边主要用了俩个插件就是proton-2.1.0.min.js和stats.min.js,这俩都是俩个对象,引入代码包之后对插件的一些属性进行设置就可以了,其中这个proton-2.1.0.min.js里边包含了很多特效,包括:火花,游戏,渲染效果,文字效果带等。感兴趣的可以看看,十分强大,效果十分炫。这款插件用法很简单,作为前端人员很快就能掌握。
这是官网给出的用法:
1 var proton = new Proton(); 2 var emitter = new Proton.Emitter(); 3 //set Rate 4 emitter.rate = new Proton.Rate(Proton.getSpan(10, 20), 0.1); 5 //add Initialize 6 emitter.addInitialize(new Proton.Radius(1, 12)); 7 emitter.addInitialize(new Proton.Life(2, 4)); 8 emitter.addInitialize(new Proton.Velocity(3, Proton.getSpan(0, 360), ‘polar‘)); 9 //add Behaviour 10 emitter.addBehaviour(new Proton.Color(‘ff0000‘, ‘random‘)); 11 emitter.addBehaviour(new Proton.Alpha(1, 0)); 12 //set emitter position 13 emitter.p.x = canvas.width / 2; 14 emitter.p.y = canvas.height / 2; 15 emitter.emit(); 16 //add emitter to the proton 17 proton.addEmitter(emitter); 18 // add canvas renderer 19 var renderer = new Proton.Renderer(‘canvas‘, proton, canvas); 20 renderer.start();
前端有很多很强大的插件,今后的博客中我还会介绍我认为很强大的一些,还有具体的用法。
烟花效果(Canvas和Proton)