乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JavaScript動畫實例:煙花綻放迎新年

       Coder編程 2021-09-28

            先編寫一個煙花綻放的動畫效果。

            放煙花時,一個煙花可分為兩個階段:(1)煙花上升到空中;(2)煙花炸開成碎片,炸開的碎片慢慢消散。

            為此抽象出兩個對象類:Firework和Particle。其中,F(xiàn)irework用于表示一個煙花對象,Particle用于表示一個煙花炸開后的各碎片。

            Firework對象類定義6個屬性:表示煙花上升軌跡中各點的坐標(x,y)、煙花弧狀軌跡的偏轉(zhuǎn)角度angle、上升階段水平和垂直方向的位移改變量xSpeed和ySpeed、煙花的色彩色相hue。

            坐標屬性值y的初始值取畫布的高度,表示煙花從地面上升到空中,其余各屬性的初始值采用隨機數(shù)確定。具體定義如下:

         function Firework()

         {

            this.x = canvas.width/4*(1+3*Math.random());

            this.y = canvas.height - 15;

            this.angle = Math.random() * Math.PI / 4 - Math.PI / 6;

            this.xSpeed = Math.sin(this.angle) *(6+Math.random()*7);

            this.ySpeed = -Math.cos(this.angle) *(6+Math.random()*7);

            this.hue = Math.floor(Math.random() * 360);

         }

            Firework對象類定義3個方法:繪制煙花上升軌跡的方法draw()、煙花上升時坐標改變方法update()和煙花炸開方法explode()。繪制煙花軌跡時,在各點(x,y)處繪制一個寬度為5、高度為15的填充小矩形表示一個軌跡點。煙花上升時,垂直方向速度ySpeed初始值為負的,每次上升時,ySpeed加上一個正值,表示上升在減速,當ySpeed的值大于0時,煙花上升到頂了(不能再上升),就炸開為70個碎片。具體方法的實現(xiàn)見后面的HTML文件內(nèi)容。

             Particle對象類定義8個屬性:表示碎片散開軌跡中各點的坐標(x,y)、碎片弧狀軌跡的偏轉(zhuǎn)角度angle、散開時水平和垂直方向的位移改變量xSpeed和ySpeed、碎片的色彩色相hue、表示碎片小圓的半徑size、碎片的亮度lightness。

         function Particle(x,y,hue)

         {

            this.x = x;

            this.y = y;

            this.hue = hue;

            this.lightness = 50;

            this.size = 15 + Math.random() * 10;

            this.angle = Math.random() * 2 * Math.PI;

            this.xSpeed = Math.cos(this.angle) *(1+Math.random() * 6);

            this.ySpeed = Math.sin(this.angle) *(1+Math.random() * 6);

         }

             Particle對象類定義2個方法:繪制碎片散開軌跡的方法draw()、碎片散開時坐標改變方法update()。碎片散開時逐漸變?。▽傩詓ize值減量),當size值小于1時,從碎片數(shù)組中刪除該碎片,表示碎片已消亡。

             定義兩個數(shù)組var fireworks=[];和var particles=[];分別存儲煙花對象和炸開的碎片對象。

             模擬動畫的函數(shù)loop中,每隔一段時間(用count計數(shù)來實現(xiàn))向fireworks數(shù)組中添加一個煙花對象,煙花對象上升到頂炸開后,從fireworks數(shù)組中刪除該對象元素,然后向particles數(shù)組中添加70個碎片對象。

            遍歷兩個數(shù)組的各對象,分別調(diào)用它們的draw()和update()方法。

      編寫的完整HTML文件內(nèi)容如下。

      <html> 
      <head> 
      <title>煙花綻放</title> 
      </head>
      <body>
      <canvas id="myCanvas" width="800" height="600" style="border:3px double #996633;background:black;">
      </canvas>
      <script type="text/javascript">
         var canvas=document.getElementById('myCanvas');
         ctx= canvas.getContext('2d');
         var fireworks=[];
         var particles=[];
         var counter = 0;
      
         function Firework()
         {
            this.x = canvas.width/4*(1+3*Math.random());
            this.y = canvas.height - 15;
            this.angle = Math.random() * Math.PI / 4 - Math.PI / 6;
            this.xSpeed = Math.sin(this.angle) *(6+Math.random()*7);
            this.ySpeed = -Math.cos(this.angle) *(6+Math.random()*7);
            this.hue = Math.floor(Math.random() * 360);
         }
         Firework.prototype.draw= function() 
         {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(Math.atan2(this.ySpeed, this.xSpeed) + Math.PI / 2);
            ctx.fillStyle =`hsl(${this.hue}, 100%, 50%)`;
            ctx.fillRect(0, 0, 5, 15);
            ctx.restore();
         }
         Firework.prototype.update= function() 
         {
            this.x = this.x + this.xSpeed;
            this.y = this.y + this.ySpeed;
            this.ySpeed += 0.1;
         }
         Firework.prototype.explode= function() 
         {
              for (var i = 0; i < 70; i++) 
             {
                particles.push(new Particle(this.x, this.y, this.hue));
             }
         }
      
         function Particle(x,y,hue) 
         {
            this.x = x;
            this.y = y;
            this.hue = hue;
            this.lightness = 50;
            this.size = 15 + Math.random() * 10;
            this.angle = Math.random() * 2 * Math.PI;
            this.xSpeed = Math.cos(this.angle) *(1+Math.random() * 6);
            this.ySpeed = Math.sin(this.angle) *(1+Math.random() * 6);
         }
         Particle.prototype.draw= function() 
         {
             ctx.fillStyle = `hsl(${this.hue}, 100%, ${this.lightness}%)`;
             ctx.beginPath();
             ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
             ctx.closePath();
             ctx.fill();
         }
         Particle.prototype.update= function(index) 
         {
             this.ySpeed += 0.05;
             this.size = this.size*0.95;
             this.x = this.x + this.xSpeed;
             this.y = this.y + this.ySpeed;
             if (this.size<1) 
             {
                 particles.splice(index,1);
             }
         }
         function loop() 
         {
            ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
            ctx.fillRect(0,0,canvas.width,canvas.height);
            counter++;
            if (counter==15) 
            {
                fireworks.push(new Firework());
                counter=0;
            }
            var i=fireworks.length;
            while (i--) 
            {
                fireworks[i].draw();
                fireworks[i].update();
                if (fireworks[i].ySpeed > 0) 
                {
                    fireworks[i].explode();
                    fireworks.splice(i, 1);
                }
            }
            var i=particles.length;
            while (i--) 
            {      
                particles[i].draw();
                particles[i].update(i);
            }
            requestAnimationFrame(loop);
         }
        loop();
      </script>
      </body> 
      </html>

            在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在瀏覽器窗口中呈現(xiàn)出如圖1所示的煙花綻放動畫效果。

       

      圖1  煙花綻放

            實現(xiàn)了煙花綻放的效果,我們還可以繼續(xù)讓一定區(qū)域內(nèi)的綻放的煙花碎片拼成“Happy New Year”粒子文本。粒子文本的實現(xiàn)方法參見文章JavaScript動畫實例:粒子文本(https://www.cnblogs.com/cs-whut/p/13334882.html)。

            編寫如下的HTML代碼。

      <html> 
      <head> 
      <title>迎新年煙花綻放</title> 
      <style>
        body { margin: 0;  background: black; }
        canvas { position: absolute; }
      </style>
      </head>
      <body>
      <canvas id="myCanvas1"></canvas>
      <canvas id="myCanvas2"></canvas>
      <canvas id="myCanvas3"></canvas>
      <script type="text/javascript">
         function Particle(x, y, hue)
         {
            this.x = x;
            this.y = y;
            this.hue = hue;
            this.lightness = 50;
            this.size = 15 + Math.random() * 10;
            this.angle = Math.random() * 2 * Math.PI;
            this.xSpeed = Math.cos(this.angle) * (1 + Math.random() * 6);
            this.ySpeed = Math.sin(this.angle) * (1 + Math.random() * 6);
            this.target = getTarget();
            this.timer = 0;
         }
         Particle.prototype.draw= function() 
         {
            ctx2.fillStyle =`hsl(${this.hue}, 100%, ${this.lightness}%)`;
            ctx2.beginPath();
            ctx2.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
            ctx2.closePath();
            ctx2.fill();
         }
         Particle.prototype.update= function(idx) 
         {
            if (this.target) 
            {
                var dx = this.target.x - this.x;
                var dy = this.target.y - this.y;
                var dist = Math.sqrt(dx * dx + dy * dy);
                var a = Math.atan2(dy, dx);
                var tx = Math.cos(a) * 5;
                var ty = Math.sin(a) * 5;
                this.size = lerp(this.size, 1.5, 0.05);
                if (dist < 5) 
                {
                   this.lightness = lerp(this.lightness, 100, 0.01);
                   this.xSpeed = this.ySpeed = 0;
                   this.x = lerp(this.x, this.target.x + fidelity / 2, 0.05);
                   this.y = lerp(this.y, this.target.y + fidelity / 2, 0.05);
                   this.timer += 1;
                }
                else if (dist < 10) 
                {
                   this.lightness = lerp(this.lightness, 100, 0.01);
                   this.xSpeed = lerp(this.xSpeed, tx, 0.1);
                   this.ySpeed = lerp(this.ySpeed, ty, 0.1);
                   this.timer += 1;
                } 
                else
                {
                   this.xSpeed = lerp(this.xSpeed, tx, 0.02);
                   this.ySpeed = lerp(this.ySpeed, ty, 0.02);
                }
            } 
            else
            {
                this.ySpeed += 0.05;
                this.size = this.size*0.95;
                if (this.size<1) 
                {
                    particles.splice(idx,1);
                }
            }
            this.x = this.x + this.xSpeed;
            this.y = this.y + this.ySpeed;
         }
      
         function Firework() 
         {
            this.x = canvas2.width*(1+ 3*Math.random())/4;
            this.y = canvas2.height - 15;
            this.angle = Math.random() * Math.PI / 4 - Math.PI / 6;
            this.xSpeed = Math.sin(this.angle) * (6 + Math.random() * 7);
            this.ySpeed = -Math.cos(this.angle) * (6 + Math.random() * 7);
            this.hue = Math.floor(Math.random() * 360);
         }
         Firework.prototype.draw= function() 
         {
            ctx2.save();
            ctx2.translate(this.x, this.y);
            ctx2.rotate(Math.atan2(this.ySpeed, this.xSpeed) + Math.PI / 2);
            ctx2.fillStyle = `hsl(${this.hue}, 100%, 50%)`;
            ctx2.fillRect(0, 0, 5, 15);
            ctx2.restore();
         }
         Firework.prototype.update= function() 
         {
            this.x = this.x + this.xSpeed;
            this.y = this.y + this.ySpeed;
            this.ySpeed += 0.1;
         }
         Firework.prototype.explode= function() 
         {
            for (var i = 0; i < 70; i++) 
            {
               particles.push(new Particle(this.x, this.y, this.hue));
            }
         }
      
         function  lerp(a, b, t)
         {
             return Math.abs(b - a)> 0.1 ? a + t * (b - a) : b;
         }
         function getTarget() 
         {
             if (targets.length > 0) 
             {
                 var idx = Math.floor(Math.random() * targets.length);
                 var { x, y } = targets[idx];
                 targets.splice(idx, 1);
                 x += canvas2.width / 2 - textWidth / 2;
                 y += canvas2.height / 2 - fontSize / 2;
                 return { x, y };
             }
         }
      
         var canvas1=document.getElementById('myCanvas1');
         ctx1= canvas1.getContext('2d');
         var canvas2=document.getElementById('myCanvas2');
         ctx2= canvas2.getContext('2d');
         var canvas3=document.getElementById('myCanvas3');
         ctx3= canvas3.getContext('2d');
         var fontSize = 200;
         var fireworks = [];
         var particles = [];
         var targets = [];
         var fidelity = 3;
         var counter = 0;
         canvas2.width = canvas3.width = window.innerWidth;
         canvas2.height = canvas3.height = window.innerHeight;
         ctx1.fillStyle = '#000';
         var text = 'Happy New Year';
         var textWidth = 999999;
         while (textWidth > window.innerWidth) 
         {
            ctx1.font = `900 ${fontSize--}px Arial`;
            textWidth = ctx1.measureText(text).width;
         }
         canvas1.width = textWidth;
         canvas1.height = fontSize * 1.5;
         ctx1.font = `900 ${fontSize}px Arial`;
         ctx1.fillText(text, 0, fontSize);
         var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height);
         for (var i = 0, max = imgData.data.length; i < max; i += 4) 
         {
             var alpha = imgData.data[i + 3];
             var x = Math.floor(i / 4) % imgData.width;
             var y = Math.floor(i / 4 / imgData.width);
             if (alpha && x % fidelity === 0 && y % fidelity === 0) 
             {
                 targets.push({ x, y });
             }
         }
         ctx3.fillStyle = '#FFF';
         ctx3.shadowColor = '#FFF';
         ctx3.shadowBlur = 25;
      
         function loop() 
         {
            ctx2.fillStyle = "rgba(0, 0, 0, .1)";
            ctx2.fillRect(0, 0, canvas2.width, canvas2.height);
            counter += 1;
            if (counter==15) 
            {
                fireworks.push(new Firework());
                counter=0;
            }
            var i=fireworks.length;
            while (i--) 
            {
                fireworks[i].draw();
                fireworks[i].update();
                if (fireworks[i].ySpeed > 0) 
                {
                    fireworks[i].explode();
                    fireworks.splice(i, 1);
                }
            }
            var i=particles.length;
            while (i--) 
            {      
               particles[i].draw();
               particles[i].update(i);
               if (particles[i].timer >= 100 || particles[i].lightness >= 99) 
               {
                   ctx3.fillRect(particles[i].target.x, particles[i].target.y, fidelity + 1, fidelity + 1);
                   particles.splice(i, 1);
               }
            }
            requestAnimationFrame(loop);
         }
         loop();
      </script>
      </body> 
      </html>
      View Code

            在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在瀏覽器窗口中呈現(xiàn)出如圖2所示的煙花綻放迎新年動畫效果。圖2中為了控制圖片的大小,刪除了大量的中間幀,因此和實際運行的效果有所不同。

       

      圖2  煙花綻放迎新年

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多