• 烟花效果(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();

     前端有很多很强大的插件,今后的博客中我还会介绍我认为很强大的一些,还有具体的用法。

  • 相关阅读:
    基于Qt的图像处理技术和算法
    项目中使用到的算法
    C++将数组的元素顺序随机打乱
    Windows环境下 RabbitMQ集群配置
    Nginx负载均衡配置
    SQL Server Profiler:使用方法和指标说明
    如何查看IIS并发连接数
    23种设计模式的趣味理解
    C# 开源框架(整理)
    git 简易教程
  • 原文地址:https://www.cnblogs.com/hgs-159/p/6032991.html
Copyright © 2020-2023  润新知