久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      HTML5 Canvas實戰(zhàn)之實現(xiàn)煙花效果的代碼案例


      1、效果

      HTML5 Canvas實戰(zhàn)之實現(xiàn)煙花效果的代碼案例

      2、代碼解析

      (1)requestAnimationFrame

      requestAnimationFrame是瀏覽器用于定時循環(huán)操作的一個接口,類似于setTimeout,主要用途是按幀對網(wǎng)頁進(jìn)行重繪。

      設(shè)置這個API的目的是為了讓各種網(wǎng)頁動畫效果(DOM動畫、Canvas動畫、SVG動畫、WebGL動畫)能夠有一個統(tǒng)一的刷新機(jī)制,從而節(jié)省系統(tǒng)資源,提高系統(tǒng)性能,改善視覺效果。代碼中使用這個API,就是告訴瀏覽器希望執(zhí)行一個動畫,讓瀏覽器在下一個動畫幀安排一次網(wǎng)頁重繪。

      requestAnimationFrame的優(yōu)勢,在于充分利用顯示器的刷新機(jī)制,比較節(jié)省系統(tǒng)資源。顯示器有固定的刷新頻率(60Hz或75Hz),也就是說,每秒最多只能重繪60次或75次,requestAnimationFrame的基本思想就是與這個刷新頻率保持同步,利用這個刷新頻率進(jìn)行頁面重繪。此外,使用這個API,一旦頁面不處于瀏覽器的當(dāng)前標(biāo)簽,就會自動停止刷新。這就節(jié)省了CPU、GPU和電力。

      不過有一點需要注意,requestAnimationFrame是在主線程上完成。這意味著,如果主線程非常繁忙,requestAnimationFrame的動畫效果會大打折扣。

      requestAnimationFrame使用一個回調(diào)函數(shù)作為參數(shù)。這個回調(diào)函數(shù)會在瀏覽器重繪之前調(diào)用。

      requestID = window.requestAnimationFrame(callback);

      目前,高版本瀏覽器Firefox 23 / IE 10 / Chrome / Safari)都支持這個方法。可以用下面的方法,檢查瀏覽器是否支持這個API。如果不支持,則自行模擬部署該方法。

      window.requestAnimFrame = (function(){        return  window.requestAnimationFrame       ||                 window.webkitRequestAnimationFrame ||                 window.mozRequestAnimationFrame    ||                 window.oRequestAnimationFrame      ||                 window.msRequestAnimationFrame     ||                 function( callback ){                  window.setTimeout(callback, 1000 / 60);                };  })();

      上面的代碼按照1秒鐘60次(大約每16.7毫秒一次),來模擬requestAnimationFrame。

      使用requestAnimationFrame的時候,只需反復(fù)調(diào)用它即可。

      function repeatOften() {  // Do whatever  requestAnimationFrame(repeatOften);  }    requestAnimationFrame(repeatOften);

      取消重繪可以用 cancelAnimationFrame。

      window.cancelAnimationFrame(requestID);

      它的參數(shù)是requestAnimationFrame返回的一個代表任務(wù)ID的整數(shù)值。

      (2)準(zhǔn)備畫版(canvas)

      判斷瀏覽器是否支持canvas,并把寬高設(shè)置為瀏覽器窗口大小。

      var canvas = document.getElementById("myCanvas");  if (!canvas.getContext) {    return;  }  canvas.width = window.innerWidth;  canvas.height = window.innerHeight;var ctx = canvas.getContext("2d");

      (3)煙花對象(FireWork)

      煙花效果可以簡單地認(rèn)為是圍繞一個點,爆炸產(chǎn)生很多小球向邊上擴(kuò)散。因此需要一個煙花對象,這個對象主要是記錄煙花綻放的位置和周圍小球的信息。所以我們的煙花對象定義如下。

      function FireWork() {      this.x = -1;      this.y = -1;      this.balls = [];  }

      那這個對象應(yīng)該有哪些方法呢?

      首先,要創(chuàng)建爆炸產(chǎn)生的小球。

      createBalls: function () {          for (var i = 0; i < 300; i++) {              var angle = Math.random() * Math.PI * 2,  radius = getRandom(50, 200);              this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius));          }      }

      注:這里fwx為煙花位置X軸坐標(biāo),fwy為煙花位置Y軸坐標(biāo),下同。

      這里小球的運(yùn)行長度為 50 到200 的隨機(jī)值,小球運(yùn)行軌跡起點為煙花位置,終點在一個圓上隨機(jī)的一點。

      然后,要對煙花進(jìn)行初始化,主要是確定位置,產(chǎn)生小球。

      init: function () {          this.x = getRandom(200, width - 200);          this.y = getRandom(200, height - 200);          fwx = this.x;          fwy = this.y;                  this.createBalls();          drawCount = 0;          currBallIndex = 0;      }

      注:這里drawCount為繪制次數(shù),currBallIndex為當(dāng)前繪制的小球索引。

      整個FireWork定義如下。

      function FireWork() {      this.x = -1;      this.y = -1;      this.balls = [];  }    FireWork.prototype = {      init: function () {              this.x = getRandom(200, width - 200);              this.y = getRandom(200, height - 200);          fwx = this.x;          fwy = this.y;                  this.createBalls();          drawCount = 0;          currBallIndex = 0;      },      run: function () {              this.init();      },      createBalls: function () {              for (var i = 0; i < 300; i++) {                  var angle = Math.random() * Math.PI * 2,                      radius = getRandom(50, 200);              this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius));          }      }  }

      (4)爆炸產(chǎn)生的小球?qū)ο?Ball)

      小球需要知道自己的起點和終點的位置,所以定義如下。

      function Ball(bx, by, ex, ey) {    this.bx = bx;//起點X軸坐標(biāo)      this.by = by;//起點Y軸坐標(biāo)      this.ex = ex;//終點X軸坐標(biāo)      this.ey = ey;//終點Y軸坐標(biāo)}

      小球還要能根據(jù)當(dāng)前繪制的次數(shù)和總繪制次數(shù)計算得到當(dāng)前坐標(biāo)和下一次繪制坐標(biāo),這兩個坐標(biāo)連接起來的直線就是本次要繪制的內(nèi)容,所以定義如下。

      Ball.prototype = {      getSpan: function () {              var xSpan = (this.ex - this.bx) / allDrawCount,              ySpan = (this.ey - this.by) / allDrawCount;                      return {              x: xSpan,              y: ySpan          };      },      currPosition: function () {              var span = this.getSpan(),              currX = -1,              currY = -1;                      if (drawCount < allDrawCount) {              currX = this.bx + span.x * (drawCount - 1);              currY = this.by + span.y * (drawCount - 1);                          return {                  x: currX,                  y: currY              };          }        return null;      },      nextPosition: function () {              var span = this.getSpan(),              currX = -1,              currY = -1;                      if (drawCount < allDrawCount) {              currX = this.bx + span.x * drawCount;              currY = this.by + span.y * drawCount;                          return {                  x: currX,                  y: currY              };          }        return null;      }  }

      (5)全局變量及工具方法

      var fwx = -1,                 //煙花位置X軸坐標(biāo)      fwy = -1,                 //煙花位置Y軸坐標(biāo)      currFW = null,            //煙花實例      currBallIndex = -1,       //當(dāng)前正在繪制的小球索引      drawCount = 0,            //繪制次數(shù)      allDrawCount = 40,        //總共需要的繪制次數(shù)      width = canvas.width,     //畫布寬度      height = canvas.height;   //畫布高度

      然后還要幾個工具方法。

      function componentToHex(c) {      var hex = c.toString(16);      return hex.length == 1 ? "0" + hex : hex;  }function rgbToHex(r, g, b) {      return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);  }function getRandom(minNum, maxNum) {      var iChoices = maxNum - minNum + 1;        return Math.floor(Math.random() * iChoices + minNum);  }

      (6)繪制方法

      最后還剩一個供 requestAnimationFrame 調(diào)用的繪制方法。這個繪制方法就是根據(jù)當(dāng)前的繪制次數(shù),拿到爆炸小球的路徑(包含起點和終點的一條線段),然后把上一次繪制的路徑擦除。

      當(dāng)一個煙花的效果繪制完成后,進(jìn)行下一個煙花的繪制。

      function drawLine(span) {      if (currFW && currBallIndex !== -1) {          if (drawCount <= allDrawCount) {              ctx.save();              drawCount++;                          for (var i = 0, j = currFW.balls.length; i < j; i++) {                              var currBall = currFW.balls[i],                      beginPoint = currBall.currPosition(),                      endPoint = currBall.nextPosition();                                      if (beginPoint && endPoint) {                      console.log(currBallIndex, drawCount, currBall, beginPoint, endPoint);                      ctx.beginPath();                      ctx.moveTo(currBall.bx, currBall.by);                      ctx.lineTo(beginPoint.x, beginPoint.y);                      ctx.strokeStyle = "#000";                      ctx.stroke();                      ctx.beginPath();                      ctx.moveTo(beginPoint.x, beginPoint.y);                      ctx.lineTo(endPoint.x, endPoint.y);                                          var r = getRandom(0, 255);                                          var g = getRandom(0, 255);                                          var b = getRandom(0, 255);                      ctx.strokeStyle = rgbToHex(r, g, b);                      ctx.stroke();                  } else {                      ctx.beginPath();                      ctx.moveTo(currBall.bx, currBall.by);                      ctx.lineTo(currBall.ex, currBall.ey);                      ctx.strokeStyle = "#000";                      ctx.stroke();                  }              }              currBallIndex++;              currBallIndex %= currFW.balls.length;              ctx.restore();          } else {              ctx.clearRect(0, 0, width, height);              currFW = new FireWork();              currFW.run();          }      }      requestAnimationFrame(drawLine);  }

      這里顏色取的是隨機(jī)值。

      (7)啟動繪制

      最后就是啟動繪制。

      currFW = new FireWork();  currFW.run();  requestAnimationFrame(drawLine);

      (8)全部代碼。

      全部代碼如下,共160行。

      1 (function () {    2     var requestAnimationFrame = window.requestAnimationFrame ||     window.mozRequestAnimationFrame ||     window.webkitRequestAnimationFrame ||     window.msRequestAnimationFrame ||      function (callback) {    3             return window.setTimeout(callback, 1000 / 60);    4         };    5     window.requestAnimationFrame = requestAnimationFrame;    6 })();    7     8 var canvas = document.getElementById("myCanvas");    9 if (!canvas.getContext) {   10     return;   11 }   12 canvas.width = window.innerWidth;   13 canvas.height = window.innerHeight;   14    15 var ctx = canvas.getContext("2d");   16    17 var fwx = -1,   18     fwy = -1,   19     currFW = null,   20     currBallIndex = -1,   21     drawCount = 0,   22     allDrawCount = 40,   23     width = canvas.width,   24     height = canvas.height;   25    26 function componentToHex(c) {   27     var hex = c.toString(16);   28     return hex.length == 1 ? "0" + hex : hex;   29 }   30    31 function rgbToHex(r, g, b) {   32     return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);   33 }   34    35 function getRandom(minNum, maxNum) {   36     var iChoices = maxNum - minNum + 1;     37     return Math.floor(Math.random() * iChoices + minNum);   38 }   39    40 function drawLine(span) {   41     if (currFW && currBallIndex !== -1) {   42         if (drawCount <= allDrawCount) {   43             ctx.save();   44             drawCount++;   45             for (var i = 0, j = currFW.balls.length; i < j; i++) {   46                 var currBall = currFW.balls[i],   47                     beginPoint = currBall.currPosition(),   48                     endPoint = currBall.nextPosition();   49                 if (beginPoint && endPoint) {   50                     console.log(currBallIndex, drawCount, currBall, beginPoint, endPoint);   51                     ctx.beginPath();   52                     ctx.moveTo(currBall.bx, currBall.by);   53                     ctx.lineTo(beginPoint.x, beginPoint.y);   54                     ctx.strokeStyle = "#000";   55                     ctx.stroke();   56                     ctx.beginPath();   57                     ctx.moveTo(beginPoint.x, beginPoint.y);   58                     ctx.lineTo(endPoint.x, endPoint.y);   59                     var r = getRandom(0, 255);   60                     var g = getRandom(0, 255);   61                     var b = getRandom(0, 255);   62                     ctx.strokeStyle = rgbToHex(r, g, b);   63                     ctx.stroke();   64                 } else {   65                     ctx.beginPath();   66                     ctx.moveTo(currBall.bx, currBall.by);   67                     ctx.lineTo(currBall.ex, currBall.ey);   68                     ctx.strokeStyle = "#000";   69                     ctx.stroke();   70                 }   71             }   72             currBallIndex++;   73             currBallIndex %= currFW.balls.length;   74             ctx.restore();   75         } else {   76             ctx.clearRect(0, 0, width, height);   77             currFW = new FireWork();   78             currFW.run();   79         }   80     }   81     requestAnimationFrame(drawLine);   82 }   83    84 function FireWork() {   85     this.x = -1;   86     this.y = -1;   87     this.balls = [];   88 }   89    90 FireWork.prototype = {   91     init: function () {   92         this.x = getRandom(200, width - 200);   93         this.y = getRandom(200, height - 200);   94         fwx = this.x;   95         fwy = this.y;   96         this.createBalls();   97         drawCount = 0;   98         currBallIndex = 0;   99     },  100     run: function () {  101         this.init();  102     },  103     createBalls: function () {  104         for (var i = 0; i < 300; i++) {  105             var angle = Math.random() * Math.PI * 2,  106                 radius = getRandom(50, 200);  107             this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius));  108         }  109     }  110 }  111   112 function Ball(bx, by, ex, ey) {  113     this.bx = bx;  114     this.by = by;  115     this.ex = ex;  116     this.ey = ey;  117 }  118   119 Ball.prototype = {  120     getSpan: function () {  121         var xSpan = (this.ex - this.bx) / allDrawCount,  122             ySpan = (this.ey - this.by) / allDrawCount;  123         return {  124             x: xSpan,  125             y: ySpan  126         };  127     },  128     currPosition: function () {  129         var span = this.getSpan(),  130             currX = -1,  131             currY = -1;  132         if (drawCount < allDrawCount) {  133             currX = this.bx + span.x * (drawCount - 1);  134             currY = this.by + span.y * (drawCount - 1);  135             return {  136                 x: currX,  137                 y: currY  138             };  139         }  140         return null;  141     },  142     nextPosition: function () {  143         var span = this.getSpan(),  144             currX = -1,  145             currY = -1;  146         if (drawCount < allDrawCount) {  147             currX = this.bx + span.x * drawCount;  148             currY = this.by + span.y * drawCount;  149             return {  150                 x: currX,  151                 y: currY  152             };  153         }  154         return null;  155     }  156 }  157   158 currFW = new FireWork();  159 currFW.run();  160 requestAnimationFrame(drawLine);

      歡迎討論。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號