<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【CSON原創】 基于HTML5的小球物理測試系統

      效果預覽:
       

      功能說明:

        一個基于HTML5 canvas的小球物理測試系統,用戶可以手動為新的小球設置不同的屬性值(顏色,半徑,速度等),從而在canvas中發射小球,小球在運動過程中會收到重力,彈性以及摩擦力的影響。

      實現原理:

      在小球飛行過程中,以初始速度,入射角以及重力系數作為依據,正交分解得出小球X軸和Y軸上的分速度,通過定時器不斷刷新canvas,顯示出小球飛行的動畫。當小球和墻壁產生碰撞時,以小球彈性為依據計算能量損耗,當小球在墻壁滾動時,以墻壁摩擦系數為依據計算其能量損耗。

      代碼分析:

      var bounceWall = (function() {


      returnfunction(canvasId,backgroundColor) {
      this.init(canvasId, backgroundColor);

      }
      })();

      構造函數,其中調用了prototype中的init方法進行初始化。需要傳入的參數是canvas的ID,和canvas的背景色,如果不傳入backgroundColor參數,背景色默認為黑色。

      bounceWall.prototype = (function() {

      var CanvasSupport = Modernizr.canvas; //檢查瀏覽器是否支持canvas
      var newBall =function(radius, color, speed, direction, currentX, currentY, elasticity) {

      this.radius = parseFloat(radius); //半徑
      this.color = color; //顏色
      this.speed = parseFloat(speed); //速度
      this.elasticity = parseFloat(elasticity); //彈性
      this.direction = parseFloat(direction); //入射角
      this.currentX = parseFloat(currentX); //初始X坐標
      this.currentY = parseFloat(currentY); //初始Y坐標
      this.dx = speed * Math.cos(this.direction * Math.PI /180); //計算其X軸方向的初始速度
      this.dy = speed * Math.sin(this.direction * Math.PI /180); //計算其Y軸方向的初始速度
      this.nextX =this.currentX +this.dx; //根據速度和初速度得出其下次移動到的X坐標
      this.nextY =this.currentY +this.dy; //根據速度和初速度得出其下次移動到的Y坐標


      };

            開始進入到bounce wall的prototype,首先使用Modernizr檢測是否可以使用canvas。Modernizr是一個可以用于檢測瀏覽器是否支持一些新功能的js庫,可以下載直接使用。

           之后出現的是小球的構造函數newBall,用戶需要傳入一系列的特性對其進行初始化,具體已經在注釋中標出。需要特別注意的是其中的nextX和nextY記錄的是小球下一次出現位置的坐標,它根據現在的位置(currentX和currentY)以及小球X軸和Y軸上的分速度(dx和dy)計算得出。nextX和nextY屬性的用處主要是保證小球能和墻壁發生完全的碰撞,會在后面的代碼分析。

      /* 繪制canvas的背景 */
      var drawBackground =function(contextObj, backgroundColor, canvasWidth, canvasHeight) {

      contextObj.fillStyle
      = backgroundColor;
      contextObj.fillRect(
      0, 0, parseInt(canvasWidth), parseInt(canvasHeight));

      };

      之后的函數是用戶繪制canvas的背景,依據的屬性是用戶設定的背景色,canvas的寬度和高度。

      /* 更新小球狀態 */

      var updateBallState =function(ballObj, canvasWidth, canvasHeight, gravityValue, friction) {

      ballObj.currentX
      = ballObj.nextX;
      ballObj.currentY
      = ballObj.nextY;
      ballObj.nextX
      = ballObj.currentX + ballObj.dx;
      ballObj.nextY
      = ballObj.currentY + ballObj.dy;

      /* 測試對墻壁產生是否X軸碰撞 */

      if (ballObj.nextX < ballObj.radius) {
      ballObj.nextX
      = ballObj.radius;
      ballObj.dx
      = Math.max(0, (ballObj.dx + ((1- ballObj.elasticity) * Math.abs(ballObj.dx))) *-1-1);
      }
      elseif ((ballObj.nextX + ballObj.radius) > parseInt(canvasWidth)) {
      ballObj.nextX
      = parseInt(canvasWidth) - ballObj.radius;
      ballObj.dx
      = Math.min(0, (ballObj.dx - ((1- ballObj.elasticity) * Math.abs(ballObj.dx))) *-1+1);
      }

      /* 水平運動時受摩擦力影響 */
      elseif (ballObj.currentY >= (parseInt(canvasHeight) - ballObj.radius)) {

      if (ballObj.dx >0) {
      ballObj.dx
      = Math.max(0, ballObj.dx - (ballObj.dx * friction) -0.01);
      }
      elseif (ballObj.dx <0) {
      ballObj.dx
      = Math.min(0, ballObj.dx - (ballObj.dx * friction) +0.01);
      }

      }


      /* 測試對墻壁產生是否Y軸碰撞 */
      if (ballObj.nextY < ballObj.radius) {
      ballObj.nextY
      = ballObj.radius;
      ballObj.dy
      = Math.max(0, (ballObj.dy + ((1- ballObj.elasticity) * Math.abs(ballObj.dy))) *-1-1);
      }
      elseif ((ballObj.nextY + ballObj.radius) > parseInt(canvasHeight)) {
      ballObj.nextY
      = parseInt(canvasHeight) - ballObj.radius;
      ballObj.dy
      = Math.min(0, (ballObj.dy - ((1- ballObj.elasticity) * Math.abs(ballObj.dy))) *-1+1);

      }
      else {
      ballObj.dy
      = ballObj.dy + gravityValue;
      }


      };

            接著是核心函數,updateBallState。該函數的作用是通過小球半徑,canvas寬高等參數,判斷小球是否和墻壁產生碰撞。并根據對四個不同墻壁的碰撞分別使用不同的處理方法。具體過程如下:

      1.首先把上次記錄的nextX和nextY設置為現在的currentX和currentY,更新了現在小球所處的位置。

      2.計算小球的nextX和nextY,這兩個參數將會決定小球下次所處的位置。

      3.如果ballObj.nextX < ballObj.radius,冊小球于左邊的墻壁碰撞,此時把nextX設置為小球半徑的值,是為了讓小球在完全和墻壁發生碰撞(和墻壁距離為0)之后,再反彈。

            之后改變小球的速度:

      ballObj.dx = Math.max(0, (ballObj.dx + ((1 - ballObj.elasticity) * Math.abs(ballObj.dx))) * -1 - 1);

            上面這個式子比較長,其中首先通過1 - ballObj.elasticity根據小球的彈性獲取一個系數,該系數越大,則小球速度減小得越多。(1 - ballObj.elasticity) * Math.abs(ballObj.dx))) 則是在獲取到剛剛的系數之后,再和小球現在的速度相乘,得到小球碰撞后減少的速度值。由此可以發現,小球彈性越好(ballObj.elasticity越大),則所減少的速度越少,每次碰撞性能損耗越少。之后再通過乘以-1把速度方向取反。可以發現最后還需要把得出的值減1,和0比較取其較大的值,這是因為小球在不斷和墻壁碰撞的過程中,由于每次都是以現有速度的百分比作為減少的速度,所以永遠都不會為0,小球永遠都不會停下。所以這里通過減1,使小球的速度小于1時,速度會自動變成0,使小球最終停下。

      4.如果不是和左邊墻壁發生碰撞,再同理判斷是否和其它墻壁碰撞,若產生碰撞,照例需要改變nextX和nextY,dx或dy的值。

      /* 把小球繪制在canvas中 */
      var drawBallsToCanvas =function(ballArray, contextObj, backgroundColor, canvasWidth, canvasHeight, gravityValue, friction) {

      returnfunction() {

      drawBackground(contextObj, backgroundColor, canvasWidth, canvasHeight);

      for (var i =0, len = ballArray.length; i < len; i++) {
      contextObj.beginPath();
      debugger;
      contextObj.fillStyle
      = ballArray[i].color;
      contextObj.arc(ballArray[i].currentX, ballArray[i].currentY, ballArray[i].radius,
      0, 2* Math.PI, false);

      contextObj.fill();
      contextObj.closePath();

      updateBallState(ballArray[i], canvasWidth, canvasHeight, gravityValue, friction);


      }
      }
      };

            這個方法主要功能是每次定時器觸發的時候,重新把所有小球繪制到canvas上。具體操作是首先重新畫canvas背景(否則在舊位置的小球會保留在canvas上并顯示出來),然后遍歷保存所有小球的數組,根據每個小球的屬性,在canvas上畫出具有新位置的小球,并調用之前的updateBallState方法,更新小球的屬性,為下次的移動作準備。

      return {
      /* 初始化函數 */
      init:
      function(canvasId, backgroundColor, friction, gravityValue) {
      if (!CanvasSupport)
      return;

      this.backgroundColor = backgroundColor ||"#000"; //背景色,默認為黑色
      this.friction = friction ||0.1; //墻壁摩擦系數,默認為0.1
      this.gravityValue = gravityValue ||0.2; //重力系數,默認為0.2
      this.canvasObj = util.$(canvasId); //canvas對象
      this.canvasWidth = util.getComputedStyle(this.canvasObj).width; //canvas高度
      this.canvasHeight = util.getComputedStyle(this.canvasObj).height;//canvas寬度
      this.contextObj =this.canvasObj.getContext('2d'); //2d的context對象
      this.ballArray = []; //保存所有小球的數組


      drawBackground(
      this.contextObj, this.backgroundColor, this.canvasWidth, this.canvasHeight);
      setInterval(drawBallsToCanvas(
      this.ballArray, this.contextObj, this.backgroundColor, this.canvasWidth, this.canvasHeight, this.gravityValue, this.friction =0.1), 33);

      },

      最后進入到返回的object,它作為bounceWall的prototype。其中有init的方法,如果瀏覽器不支持canvas則返回,否則初始化一切初始屬性,并啟動setInternal定時器定時更新canvas的狀態。

      /* 添加小球 */
      createBall:
      function(radius, color, speed, direction, currentX, currentY, elasticity) {// 小球半徑 顏色 速度 方向

      var ball =new newBall(radius, color, speed, direction, currentX, currentY, elasticity);


      this.ballArray.push(ball);

      }

      }

      })();

      添加小球的方法,demo中,該方法在“添加小球”的事件處理程序中被調用,根據用戶輸入數據進行新小球的添加。

      var wall =new bounceWall('wallCanvas', '#000'); //創建bounce wall

      var radiusInput = util.$('radiusInput'); //半徑輸入文本框
      var color_Input = util.$('color_Input'); //顏色輸入文本框
      var speed_Input = util.$('speed_Input'); //速度輸入文本框
      var elaticity_Input = util.$('elaticity_Input'); //彈性輸入文本框
      var inAngle_Input = util.$('inAngle_Input'); //入射角輸入文本框
      var X_Input = util.$('X_Input'); //初始X坐標輸入文本框
      var Y_Input = util.$('Y_Input'); //初始Y坐標輸入文本框


      var btn = util.$('add_btn'); //添加小球按鈕
      btn.onclick =function() { //綁定事件處理程序,調用creatBall方法創建新小球
      wall.createBall(radiusInput.value, color_Input.value, speed_Input.value, inAngle_Input.value, X_Input.value, Y_Input.value, elaticity_Input.value);

      }

      最后是demo中調用的代碼。

      完整demo代碼:

       

      View Code
      *{margin:0; padding:0;}
      body
      {text-align:center;}

      ul
      {list-style-type:none;}
      #inputTable
      {width:200px; height:200px; margin:0 auto;}
      #inputTable input
      {width:50px;}
      View Code
      <!doctype html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>Bounce Wall</title>
      <link href="bounceWall.css" rel="stylesheet" type="text/css"/>
      </head>
      <body>

      <canvas id="wallCanvas" width="400px" height="400px">
      Your browser does not support HTML5 Canvas.
      </canvas>
      <table id="inputTable">
      <tr><td><label>半徑:</label></td><td><input id="radiusInput" type="text"/></td></tr>

      <tr><td><label>顏色:</label></td><td><input id="color_Input" type="text"/></td></tr>
      <tr><td><label>速度:</label></td><td><input id="speed_Input" type="text"/></td></tr>
      <tr><td><label>彈性(0-1):</label></td><td><input id="elaticity_Input" type="text"/></td></tr>
      <tr><td><label>入射角(0-360):</label></td><td><input id="inAngle_Input" type="text"/></td></tr>
      <tr><td><label>起始X坐標(0-600):</label></td><td><input id="X_Input" type="text"/></td></tr>
      <tr><td><label>起始Y坐標(0-600):</label></td><td><input id="Y_Input" type="text"/></td></tr>

      </table>
      <input id="add_btn" type="button" value="添加小球"/>
      </body>

      <script src="util.js" type="text/javascript"></script>
      <script src="modernizr.js" type="text/javascript"></script>
      <script src="bounceWall.js" type="text/javascript"></script>
      <script>
      var wall =new bounceWall('wallCanvas', '#000'); //創建bounce wall

      var radiusInput = util.$('radiusInput'); //半徑輸入文本框
      var color_Input = util.$('color_Input'); //顏色輸入文本框
      var speed_Input = util.$('speed_Input'); //速度輸入文本框
      var elaticity_Input = util.$('elaticity_Input'); //彈性輸入文本框
      var inAngle_Input = util.$('inAngle_Input'); //入射角輸入文本框
      var X_Input = util.$('X_Input'); //初始X坐標輸入文本框
      var Y_Input = util.$('Y_Input'); //初始Y坐標輸入文本框


      var btn = util.$('add_btn'); //添加小球按鈕
      btn.onclick =function() { //綁定事件處理程序,調用creatBall方法創建新小球
      wall.createBall(radiusInput.value, color_Input.value, speed_Input.value, inAngle_Input.value, X_Input.value, Y_Input.value, elaticity_Input.value);

      }

      </script>
      </html>
      View Code
      var bounceWall = (function() {


      returnfunction(canvasId,backgroundColor) {
      this.init(canvasId, backgroundColor);

      }
      })();

      bounceWall.prototype
      = (function() {

      var CanvasSupport = Modernizr.canvas; //檢查瀏覽器是否支持canvas
      var newBall =function(radius, color, speed, direction, currentX, currentY, elasticity) {

      this.radius = parseFloat(radius); //半徑
      this.color = color; //顏色
      this.speed = parseFloat(speed); //速度
      this.elasticity = parseFloat(elasticity); //彈性
      this.direction = parseFloat(direction); //入射角
      this.currentX = parseFloat(currentX); //初始X坐標
      this.currentY = parseFloat(currentY); //初始Y坐標
      this.dx = speed * Math.cos(this.direction * Math.PI /180); //計算其X軸方向的初始速度
      this.dy = speed * Math.sin(this.direction * Math.PI /180); //計算其Y軸方向的初始速度
      this.nextX =this.currentX +this.dx; //根據速度和初速度得出其下次移動到的X坐標
      this.nextY =this.currentY +this.dy; //根據速度和初速度得出其下次移動到的Y坐標


      };


      /* 繪制canvas的背景 */
      var drawBackground =function(contextObj, backgroundColor, canvasWidth, canvasHeight) {

      contextObj.fillStyle
      = backgroundColor;
      contextObj.fillRect(
      0, 0, parseInt(canvasWidth), parseInt(canvasHeight));

      };


      /* 更新小球狀態 */

      var updateBallState =function(ballObj, canvasWidth, canvasHeight, gravityValue, friction) {

      ballObj.currentX
      = ballObj.nextX;
      ballObj.currentY
      = ballObj.nextY;
      ballObj.nextX
      = ballObj.currentX + ballObj.dx;
      ballObj.nextY
      = ballObj.currentY + ballObj.dy;

      /* 測試對墻壁產生是否X軸碰撞 */

      if (ballObj.nextX < ballObj.radius) {
      ballObj.nextX
      = ballObj.radius;
      ballObj.dx
      = Math.max(0, (ballObj.dx + ((1- ballObj.elasticity) * Math.abs(ballObj.dx))) *-1-1);
      }
      elseif ((ballObj.nextX + ballObj.radius) > parseInt(canvasWidth)) {
      ballObj.nextX
      = parseInt(canvasWidth) - ballObj.radius;
      ballObj.dx
      = Math.min(0, (ballObj.dx - ((1- ballObj.elasticity) * Math.abs(ballObj.dx))) *-1+1);
      }

      /* 水平運動時受摩擦力影響 */
      elseif (ballObj.currentY >= (parseInt(canvasHeight) - ballObj.radius)) {

      if (ballObj.dx >0) {
      ballObj.dx
      = Math.max(0, ballObj.dx - (ballObj.dx * friction) -0.01);
      }
      elseif (ballObj.dx <0) {
      ballObj.dx
      = Math.min(0, ballObj.dx - (ballObj.dx * friction) +0.01);
      }

      }


      /* 測試對墻壁產生是否Y軸碰撞 */
      if (ballObj.nextY < ballObj.radius) {
      ballObj.nextY
      = ballObj.radius;
      ballObj.dy
      = Math.max(0, (ballObj.dy + ((1- ballObj.elasticity) * Math.abs(ballObj.dy))) *-1-1);
      }
      elseif ((ballObj.nextY + ballObj.radius) > parseInt(canvasHeight)) {
      ballObj.nextY
      = parseInt(canvasHeight) - ballObj.radius;
      ballObj.dy
      = Math.min(0, (ballObj.dy - ((1- ballObj.elasticity) * Math.abs(ballObj.dy))) *-1+1);

      }
      else {
      ballObj.dy
      = ballObj.dy + gravityValue;
      }


      };




      /* 把小球繪制在canvas中 */
      var drawBallsToCanvas =function(ballArray, contextObj, backgroundColor, canvasWidth, canvasHeight, gravityValue, friction) {

      returnfunction() {

      drawBackground(contextObj, backgroundColor, canvasWidth, canvasHeight);

      for (var i =0, len = ballArray.length; i < len; i++) {
      contextObj.beginPath();
      debugger;
      contextObj.fillStyle
      = ballArray[i].color;
      contextObj.arc(ballArray[i].currentX, ballArray[i].currentY, ballArray[i].radius,
      0, 2* Math.PI, false);

      contextObj.fill();
      contextObj.closePath();

      updateBallState(ballArray[i], canvasWidth, canvasHeight, gravityValue, friction);


      }
      }
      };




      return {
      /* 初始化函數 */
      init:
      function(canvasId, backgroundColor, friction, gravityValue) {
      if (!CanvasSupport)
      return;

      this.backgroundColor = backgroundColor ||"#000"; //背景色,默認為黑色
      this.friction = friction ||0.1; //墻壁摩擦系數,默認為0.1
      this.gravityValue = gravityValue ||0.2; //重力系數,默認為0.2
      this.canvasObj = util.$(canvasId); //canvas對象
      this.canvasWidth = util.getComputedStyle(this.canvasObj).width; //canvas高度
      this.canvasHeight = util.getComputedStyle(this.canvasObj).height;//canvas寬度
      this.contextObj =this.canvasObj.getContext('2d'); //2d的context對象
      this.ballArray = []; //保存所有小球的數組


      drawBackground(
      this.contextObj, this.backgroundColor, this.canvasWidth, this.canvasHeight);
      setInterval(drawBallsToCanvas(
      this.ballArray, this.contextObj, this.backgroundColor, this.canvasWidth, this.canvasHeight, this.gravityValue, this.friction =0.1), 33);

      },
      /* 添加小球 */
      createBall:
      function(radius, color, speed, direction, currentX, currentY, elasticity) {// 小球半徑 顏色 速度 方向

      var ball =new newBall(radius, color, speed, direction, currentX, currentY, elasticity);


      this.ballArray.push(ball);

      }

      }

      })();

      歡迎轉載,請標明出處:http://www.rzrgm.cn/Cson/archive/2011/06/30/2094752.html

      posted @ 2011-06-30 17:57  Cson  閱讀(3818)  評論(22)    收藏  舉報
      主站蜘蛛池模板: 一区二区三区四区自拍视频| 国产婷婷综合在线视频中文| 百色市| 精品无码久久久久国产电影| 日本道高清一区二区三区| 亚洲a免费| 成人午夜大片免费看爽爽爽| 国产综合色产在线视频欧美| 久久毛片少妇高潮| 国产亚洲精品日韩av在| 熟妇人妻av中文字幕老熟妇 | 最新精品国偷自产在线美女足| 国产一区二区三区不卡视频| 亚洲一区二区三区丝袜| 国产极品粉嫩尤物一线天| 午夜毛片不卡免费观看视频| 国产无套精品一区二区三区| 久久精品国产99精品亚洲| 国产香蕉尹人在线视频你懂的| 91中文字幕在线一区| 99精品国产综合久久久久五月天| 久久―日本道色综合久久| 国产黄色带三级在线观看| 亚洲av本道一区二区| 日韩高清国产中文字幕| 青青草无码免费一二三区| 丰满人妻AV无码一区二区三区 | 国内自拍偷拍一区二区三区 | 自拍偷在线精品自拍偷99| 亚洲最大国产成人综合网站 | 无码 人妻 在线 视频| 噜噜综合亚洲av中文无码| 精品少妇后入一区二区三区| 蜜桃av亚洲第一区二区| 深夜视频国产在线观看| 日韩乱码人妻无码中文字幕视频| 乱中年女人伦av三区| 377P欧洲日本亚洲大胆| 男人av无码天堂| 人妻系列无码专区无码中出| 人人玩人人添人人澡超碰|