ホームページ > ウェブフロントエンド > H5 チュートリアル > HTML5 Canvas で花火が咲く特殊効果を実現

HTML5 Canvas で花火が咲く特殊効果を実現

不言
リリース: 2018-07-03 12:00:46
オリジナル
18154 人が閲覧しました

これは、私たちの生活に咲く花火のアニメーション特殊効果をシミュレートするものです。興味のある読者の皆さん、この効果を実装するプロセスとコードを簡単に分析してみましょう。参考にしてください

この記事では、HTML5 Canvas で実装された、無料で安全で環境に優しい花火の特殊効果を紹介します。

効果は次のとおりです:

コードは次のとおりです:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Canvas 实现放烟花特效</title>
 <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style type="text/css">
  html,body{height:100%;margin:0;padding:0}   
  ul,li{text-indent:0;text-decoration:none;margin:0;padding:0}   
  img{border:0}   
  body{background-color:#000;color:#999;font:100%/18px helvetica, arial, sans-serif}   
  canvas{cursor:crosshair;display:block;left:0;position:absolute;top:0;z-index:20}   
  #header img{width:100%; height:20%;}   
  #bg img{width:100%; height:80%;}   
  #header,#bg{position:fixed;left:0;right:0;z-index:10}   
  #header{top:0}   
  #bg{position:fixed;z-index:1;bottom:0}   
  audio{position:fixed;display:none;bottom:0;left:0;right:0;width:100%;z-index:5}   
 </style>
  </head>
  <body>
 <p id="bg">
  <img id="bgimg" src="http://img.ivsky.com/img/tupian/pre/201508/02/yuzhou_xingkong_yu_yueliang-006.jpg">
 </p>
 <script src="http://cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script>
 <script>
  $(function(){   
   var Fireworks = function(){   
    var self = this;   
    // 产生烟花随机数   
    var rand = function(rMi, rMa){   
     //按位取反运算符   
     return ~~((Math.random()*(rMa-rMi+1))+rMi);   
    },hitTest = function(x1, y1, w1, h1, x2, y2, w2, h2){   
     return !(x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1);   
    };   
    //请求动画帧   
    window.requestAnimFrame=function(){   
     return window.requestAnimationFrame   
      ||window.webkitRequestAnimationFrame   
      ||window.mozRequestAnimationFrame   
      ||window.oRequestAnimationFrame   
      ||window.msRequestAnimationFrame   
      ||function(callback){   
       window.setTimeout(callback,1000/60);   
      }   
    }();   
    self.init = function(){    
     self.canvas = document.createElement(&#39;canvas&#39;);     
     //canvas 全屏   
     selfself.canvas.width = self.cw = $(window).innerWidth();   
     selfself.canvas.height = self.ch = $(window).innerHeight();     
     self.particles = [];    
     self.partCount = 150;   
     self.fireworks = [];    
     selfself.mx = self.cw/2;   
     selfself.my = self.ch/2;   
     self.currentHue = 30;   
     self.partSpeed = 5;   
     self.partSpeedVariance = 10;   
     self.partWind = 50;   
     self.partFriction = 5;   
     self.partGravity = 1;   
     self.hueMin = 0;   
     self.hueMax = 360;   
     self.fworkSpeed = 4;   
     self.fworkAccel = 10;   
     self.hueVariance = 30;   
     self.flickerDensity = 25;   
     self.showShockwave = true;   
     self.showTarget = false;   
     self.clearAlpha = 25;   
     $(document.body).append(self.canvas);   
     selfself.ctx = self.canvas.getContext(&#39;2d&#39;);   
     self.ctx.lineCap = &#39;round&#39;;   
     self.ctx.lineJoin = &#39;round&#39;;   
     self.lineWidth = 1;   
     self.bindEvents();      
     self.canvasLoop();   
     self.canvas.onselectstart = function() {   
      return false;   
     };   
    };     
    // 创建粒子   
    self.createParticles = function(x,y, hue){   
     var countdown = self.partCount;   
     while(countdown--){   
      var newParticle = {   
       x: x,   
       y: y,   
       coordLast: [   
        {x: x, y: y},   
        {x: x, y: y},   
        {x: x, y: y}   
       ],   
       angle: rand(0, 360),   
       speed: rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance)),   
       friction: 1 - self.partFriction/100,   
       gravity: self.partGravity/2,   
       hue: rand(hue-self.hueVariance, hue+self.hueVariance),   
       brightness: rand(50, 80),   
       alpha: rand(40,100)/100,   
       decay: rand(10, 50)/1000,   
       wind: (rand(0, self.partWind) - (self.partWind/2))/25,   
       lineWidth: self.lineWidth   
      };       
      self.particles.push(newParticle);   
     }   
    };   
    // 更新粒子   
    self.updateParticles = function(){   
     var i = self.particles.length;   
     while(i--){   
      var p = self.particles[i];   
      var radians = p.angle * Math.PI / 180;   
      var vx = Math.cos(radians) * p.speed;   
      var vy = Math.sin(radians) * p.speed;   
      p.speed *= p.friction;   
      p.coordLast[2].x = p.coordLast[1].x;   
      p.coordLast[2].y = p.coordLast[1].y;   
      p.coordLast[1].x = p.coordLast[0].x;   
      p.coordLast[1].y = p.coordLast[0].y;   
      p.coordLast[0].x = p.x;   
      p.coordLast[0].y = p.y;   
      p.x += vx;   
      p.y += vy;   
      p.y += p.gravity;   
      p.angle += p.wind;       
      p.alpha -= p.decay;   
      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){        
       self.particles.splice(i, 1);    
      }   
     };   
    };   
    // 绘制粒子   
    self.drawParticles = function(){   
     var i = self.particles.length;   
     while(i--){   
      var p = self.particles[i];          
      var coordRand = (rand(1,3)-1);   
      self.ctx.beginPath();           
      self.ctx.moveTo(Math.round(p.coordLast[coordRand].x), Math.round(p.coordLast[coordRand].y));   
      self.ctx.lineTo(Math.round(p.x), Math.round(p.y));   
      self.ctx.closePath();       
      self.ctx.strokeStyle = &#39;hsla(&#39;+p.hue+&#39;, 100%, &#39;+p.brightness+&#39;%, &#39;+p.alpha+&#39;)&#39;;   
      self.ctx.stroke();       
      if(self.flickerDensity > 0){   
       var inverseDensity = 50 - self.flickerDensity;        
       if(rand(0, inverseDensity) === inverseDensity){   
        self.ctx.beginPath();   
        self.ctx.arc(Math.round(p.x), Math.round(p.y), rand(p.lineWidth,p.lineWidth+3)/2, 0, Math.PI*2, false)   
        self.ctx.closePath();   
        var randrandAlpha = rand(50,100)/100;   
        self.ctx.fillStyle = &#39;hsla(&#39;+p.hue+&#39;, 100%, &#39;+p.brightness+&#39;%, &#39;+randAlpha+&#39;)&#39;;   
        self.ctx.fill();   
       }    
      }   
     };   
    };   
    // 创建烟花       
    self.createFireworks = function(startX, startY, targetX, targetY){   
     var newFirework = {   
      x: startX,   
      y: startY,   
      startX: startX,   
      startY: startY,   
      hitX: false,   
      hitY: false,   
      coordLast: [   
       {x: startX, y: startY},   
       {x: startX, y: startY},   
       {x: startX, y: startY}   
      ],   
      targetX: targetX,   
      targetY: targetY,   
      speed: self.fworkSpeed,   
      angle: Math.atan2(targetY - startY, targetX - startX),   
      shockwaveAngle: Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180)),   
      acceleration: self.fworkAccel/100,   
      hue: self.currentHue,   
      brightness: rand(50, 80),   
      alpha: rand(50,100)/100,   
      lineWidth: self.lineWidth   
     };      
     self.fireworks.push(newFirework);   
    };   
    // 更新烟花   
    self.updateFireworks = function(){   
     var i = self.fireworks.length;   
     while(i--){   
      var f = self.fireworks[i];   
      self.ctx.lineWidth = f.lineWidth;   
      vx = Math.cos(f.angle) * f.speed,   
      vy = Math.sin(f.angle) * f.speed;   
      f.speed *= 1 + f.acceleration;       
      f.coordLast[2].x = f.coordLast[1].x;   
      f.coordLast[2].y = f.coordLast[1].y;   
      f.coordLast[1].x = f.coordLast[0].x;   
      f.coordLast[1].y = f.coordLast[0].y;   
      f.coordLast[0].x = f.x;   
      f.coordLast[0].y = f.y;   
      if(f.startX >= f.targetX){   
       if(f.x + vx <= f.targetX){   
        ff.x = f.targetX;   
        f.hitX = true;   
       } else {   
        f.x += vx;   
       }   
      } else {   
       if(f.x + vx >= f.targetX){   
        ff.x = f.targetX;   
        f.hitX = true;   
       } else {   
        f.x += vx;   
       }   
      }   
      if(f.startY >= f.targetY){   
       if(f.y + vy <= f.targetY){   
        ff.y = f.targetY;   
        f.hitY = true;   
       } else {   
        f.y += vy;   
       }   
      } else {   
       if(f.y + vy >= f.targetY){   
        ff.y = f.targetY;   
        f.hitY = true;   
       } else {   
        f.y += vy;   
       }   
      }       
      if(f.hitX && f.hitY){   
       self.createParticles(f.targetX, f.targetY, f.hue);   
       self.fireworks.splice(i, 1);   
      }   
     };   
    };   
    // 绘制烟花   
    self.drawFireworks = function(){   
     var i = self.fireworks.length;   
     self.ctx.globalCompositeOperation = &#39;lighter&#39;;   
     while(i--){   
      var f = self.fireworks[i];     
      self.ctx.lineWidth = f.lineWidth;   
      var coordRand = (rand(1,3)-1);        
      self.ctx.beginPath();          
      self.ctx.moveTo(Math.round(f.coordLast[coordRand].x), Math.round(f.coordLast[coordRand].y));   
      self.ctx.lineTo(Math.round(f.x), Math.round(f.y));   
      self.ctx.closePath();   
      self.ctx.strokeStyle = &#39;hsla(&#39;+f.hue+&#39;, 100%, &#39;+f.brightness+&#39;%, &#39;+f.alpha+&#39;)&#39;;   
      self.ctx.stroke();    
      if(self.showTarget){   
       self.ctx.save();   
       self.ctx.beginPath();   
       self.ctx.arc(Math.round(f.targetX), Math.round(f.targetY), rand(1,8), 0, Math.PI*2, false)   
       self.ctx.closePath();   
       self.ctx.lineWidth = 1;   
       self.ctx.stroke();   
       self.ctx.restore();   
      }   
      if(self.showShockwave){   
       self.ctx.save();   
       self.ctx.translate(Math.round(f.x), Math.round(f.y));   
       self.ctx.rotate(f.shockwaveAngle);   
       self.ctx.beginPath();   
       self.ctx.arc(0, 0, 1*(f.speed/5), 0, Math.PI, true);   
       self.ctx.strokeStyle = &#39;hsla(&#39;+f.hue+&#39;, 100%, &#39;+f.brightness+&#39;%, &#39;+rand(25, 60)/100+&#39;)&#39;;   
       self.ctx.lineWidth = f.lineWidth;   
       self.ctx.stroke();   
       self.ctx.restore();   
      }   
     };   
    };   
    // 绑定事件   
    self.bindEvents = function(){   
     $(window).on(&#39;resize&#39;, function(){      
      clearTimeout(self.timeout);   
      self.timeout = setTimeout(function() {   
       selfself.canvas.width = self.cw = $(window).innerWidth();   
       selfself.canvas.height = self.ch = $(window).innerHeight();   
       self.ctx.lineCap = &#39;round&#39;;   
       self.ctx.lineJoin = &#39;round&#39;;   
      }, 100);   
     });   
     $(self.canvas).on(&#39;mousedown&#39;, function(e){   
      self.mx = e.pageX - self.canvas.offsetLeft;   
      self.my = e.pageY - self.canvas.offsetTop;   
      self.currentHue = rand(self.hueMin, self.hueMax);   
      self.createFireworks(self.cw/2, self.ch, self.mx, self.my);    
      $(self.canvas).on(&#39;mousemove.fireworks&#39;, function(e){   
       self.mx = e.pageX - self.canvas.offsetLeft;   
       self.my = e.pageY - self.canvas.offsetTop;   
       self.currentHue = rand(self.hueMin, self.hueMax);   
       self.createFireworks(self.cw/2, self.ch, self.mx, self.my);            
      });       
     });   
     $(self.canvas).on(&#39;mouseup&#39;, function(e){   
      $(self.canvas).off(&#39;mousemove.fireworks&#39;);            
     });   
    };   
    self.clear = function(){   
     self.particles = [];   
     self.fireworks = [];   
     self.ctx.clearRect(0, 0, self.cw, self.ch);   
    };   
    self.canvasLoop = function(){   
     requestAnimFrame(self.canvasLoop, self.canvas);      
     self.ctx.globalCompositeOperation = &#39;destination-out&#39;;   
     self.ctx.fillStyle = &#39;rgba(0,0,0,&#39;+self.clearAlpha/100+&#39;)&#39;;   
     self.ctx.fillRect(0,0,self.cw,self.ch);   
     self.updateFireworks();   
     self.updateParticles();   
     self.drawFireworks();      
     self.drawParticles();   
    };   
    self.init();     
   }   
   var fworks = new Fireworks();   
   $(&#39;#info-toggle&#39;).on(&#39;click&#39;, function(e){   
    $(&#39;#info-inner&#39;).stop(false, true).slideToggle(100);   
    e.preventDefault();   
   });    
  });   
 </script>
 <canvas width="1400" height="449"></canvas>
  </body>
</html>
ログイン後にコピー

HTML5 の強力な効果に驚かれていますか?

上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連する推奨事項:

ダイナミックなボールの重なり合うコードの効果を実現するキャンバス

愛と虹の雨の効果を実現するキャンバス

キャンバスを使用して「ドラえもん」の時計を描画するコード

以上がHTML5 Canvas で花火が咲く特殊効果を実現の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート