HTML5 Canvas实战
5.10 创建微生物生命形态
阅读(

路径和文本

图形及组合

处理图像和视频

画布变换

动画给画布带来生机

创建Animation类

创建直线运动

创建加速度

创建振荡运动

摆动的气泡

摆钟

动画机械齿轮

动画时钟

模拟粒子物理学

创建微生物生命形态

你曾经在显微镜下看到过微生物生命形态,并观察它们是如何四处扭动吗?本节就是受微生物世界的启发而产生的。本节,我们将随机创建100个的微生物,并让它们散落在画布上。

创建微生物生命形态
图5-10 创建微生物生命形态

操作步骤

按照以下步骤,创建在画布内随意扭动的微生物:

1. 链接到Animation类:

<head>
<script src="animation.js">
</script>

2. 定义getRandColor()函数,该函数返回一个随机的颜色:

<script>
function getRandColor(){
  var colors  =  ["red", "orange", "yellow", "green",  "blue", "violet"];
  return colors[Math.floor(Math.random() * colors.length)];
}

3. 定义getRandTheta()函数,该函数返回一个随机的角度:

function getRandTheta(){
  return Math.random()  *  2  * Math.PI;
}

4. 定义updateMicrobes()函数,该函数使用随机产生的角度为每个微生物添加头部,并去掉其尾部,来更新microbe对象:

function updateMicrobes(anim, microbes){
  var canvas  = anim.getCanvas();
  var angleVariance  =  0.2;
  for  (var i  =  0; i  < microbes.length; i++)  {
    var microbe  = microbes[i];
    var angles  = microbe.angles;
    /*
    * good numNewSegmentsPerFrame values: *  60fps  ->  1
    *  10fps  ->  10 
    *
    * for a linear relationship, we can use the equation:
             * n  = mf  + b, where n  = numNewSegmentsPerFrame and f  =
     FPS
    * solving for m and b, we have: * n  =  (-0.18)f  +  11.8
    */
    var numNewSegmentsPerFrame  = Math.round(-0.18 * anim.getFps()  +  11.8);
    for  (var n  =  0; n  < numNewSegmentsPerFrame; n++)  {
      // create first angle if no angles
      if  (angles.length  ==  0)  {
        microbe.headX  = canvas.width  /  2;
        microbe.headY  = canvas.height  /  2;
        angles.push(getRandTheta());
      }
      var headX  = microbe.headX;
      var headY  = microbe.headY;
      var headAngle  = angles[angles.length  -  1];
      // create new head angle
      var dist  = anim.getTimeInterval()  /  (10 *  numNewSegmentsPerFrame);
      // increase new head angle by an amount equal  to
      //  -0.1 to  0.1
      var newHeadAngle  = headAngle  +  ((angleVariance   /  2)  - Math.random()  * angleVariance);
      var newHeadX  = headX  + dist  * Math.cos(newHeadAngle);
      var newHeadY  = headY  + dist  * Math.sin(newHeadAngle);
      //发生碰撞后改变方向
      if  (newHeadX  >= canvas.width  || newHeadX  <=  0
        || newHeadY  >= canvas.height || newHeadY  <=  0)  {
        newHeadAngle  += Math.PI  /  2;
        newHeadX  = headX  + dist  * Math.cos(newHeadAngle);
        newHeadY  = headY  + dist  * Math.sin(newHeadAngle);
      }
      microbe.headX  = newHeadX;
      microbe.headY  = newHeadY;
      angles.push(newHeadAngle);
      //去掉尾部角度
      if  (angles.length  >  20)  {
          angles.shift();
      }
    }
   }
}

5. 定义drawMicrobes()函数,该函数绘制所有微生物:

function drawMicrobes(anim, microbes){
  var segmentLength  =  2;  // px
  var context  = anim.getContext();
  for  (var i  =  0; i  < microbes.length; i++)  {
    var microbe = microbes[i];
    var angles  = microbe.angles;
    context.beginPath();
    context.moveTo(microbe.headX, microbe.headY);
    var x  = microbe.headX;
    var y  = microbe.headY;
    // 从头部开始,到尾巴结束
    for  (var n  = angles.length  -  1; n  >=  0; n--)  {
      var angle  = angles[n];
      x  -= segmentLength  * Math.cos(angle);
      y  -= segmentLength  * Math.sin(angle);       
      context.lineTo(x, y);
    }
    context.lineWidth =  10;
    context.lineCap   = "round";
    context.lineJoin  = "round";
    context.strokeStyle  = microbe.color; 
    context.stroke();
  }
}

6. 实例化一个Animation对象,并得到画布上下文对象:

window.onload  = function(){
  var anim  = new Animation("myCanvas"); 
  var canvas  = anim.getCanvas();
  var context  = anim.getContext();

7. 初始化100个微生物:

  //初始化微生物
  var microbes  =  [];
  for  (var n  =  0; n  <  100; n++)  {
    // 每个微生物都是一个角度的数组
    microbes[n]  =  {
      headX:  0,
      headY:  0,
      angles:  [],
      color: getRandColor()
    };
  }

8. 设置stage()函数,该函数通过调用updateMicrobes()函数来更新微生物,清除画布,然后调用drawMicrobes()函数绘制微生物:

anim.setStage(function(){
  // update
  updateMicrobes(this, microbes);
  // clear
  this.clear();
  // draw
  drawMicrobes(this, microbes);
});

9. 启动动画:

  anim.start();
};
</script>
</head>

10. 在HTML文档的body部分嵌入canvas标签:

<body>
<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>
</body>

工作原理

要创建微生物,我们可以绘制一系列连接的小段来创建一个短小的蛇形生物。我们可以把一个微生物为表示一个对象,该对象包含一个头部位置和一个角度的数组。这些角度代表各段之间的夹角。

本节创建了100个随机的微生物,并把它们放置在画布的中央。我们的stage()函数包含updateMicrobes()函数和drawMicrobes()函数。

updateMicrobes ()函数循环所有的微生物对象,为每个微生物其增加一个头段,并去掉其尾段。用这个办法,当每个微生物在画布上移动时,将会发生扭动。当微生物的头碰到画布边缘,其角度会增加90°,以便能够弹回到画布区域。

drawMicrobes()函数循环所有的微生物对象,把绘制光标定位到每个微生物的头部,然后根据每段的角度绘制20条线段。

相关参考

  • 第1章 绘制弹簧
  • 第6章 创建绘图应用

如果本教程对您帮助很大,请随意打赏。您的支持,将鼓励我们提供更好的教程!

← 键盘方向键翻页 →
返回顶部 手机访问 关注微信 返回底部

扫码访问歪脖网

随时随地,想看就看

关注歪脖网微信

分享 web 知识、交流 web 经验