canvas网格蠕虫动画效果

代码语言:html

所属分类:动画

代码描述:canvas网格蠕虫动画效果

代码标签: 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">


</head>
<body translate="no">
<canvas id='gridwormCanvas' width='1350' height='620' style='background-color: white;'></canvas>

<script>
/*
 *Animates connected nodes about a grid
 *------------------------------------- 
 *@author:    Caleb Nii Tetteh Tsuru Addy 
 *@date:      19th April, 2020 
 *@email:     calebniitettehaddy@gmail.com 
 *@twitter:   @cnttaddy
 *@github :   https://github.com/niitettehtsuru/GridWorms 
 *@license:   GNU General Public License v3.0
 */
//set up the gridworm
class GridWorm
{
  constructor(point, interval, pointsList, screenWidth, screenHeight)
  {
    this.radius = 2;
    this.xCoord = point.x;
    this.yCoord = point.y;
    this.interval = interval;
    this.color = this.getColor(1, true); //get random color object
    this.mainColor = this.color.color; //color of the head and body of the girdworm
    this.mainColorIndex = this.color.index;
    this.nColor = this.getColor(1, true); //get another random color object
    this.arrowHeadColor = this.nColor.color; //color of the arrrow points at the head of the gridworm
    this.arrowHeadColorIndex = this.nColor.index;
    this.pointsList = pointsList;
    this.screenWidth = screenWidth;
    this.screenHeight = screenHeight;
    this.speed = 5; //the magnitude of the velocity
    this.velocity = this.getVelocity();
    this.junctionMemory = [{ point: point, velocity: this.velocity }]; //memory of each junction visited(helps to construct the worm)
    //the maximum number of junctions a gridworm can keep in memory(this determines how long the gridworm will be)
    this.junctionMemoryLength = 6;
  }
  getColor(opacity, isRandom = true, index = 0)
  {
    if (opacity < 0 || opacity > 1 || opacity === null || isNaN(opacity)) //if opacity is incorrect
      {
        opacity = 1;
      }
    var colors =
    [
    `rgba(0,0,0,${opacity})`, `rgba(192,192,192,${opacity})` /*silver*/, `rgba(128,128,128,${opacity})` /*gray*/, `rgba(128,0,0,${opacity})` /*maroon*/,
    `rgba(255,0,0,${opacity})` /*red*/, `rgba(0,255,0,${opacity})` /*lime*/, `rgba(0,0,255,${opacity})` /*blue*/, `rgba(255,0,255,${opacity})` /*fuchsia*/,
    `rgba(128,128,0,${opacity})` /*olive*/, `rgba(0,128,0,${opacity})` /*green*/, `rgba(128,0,128,${opacity})` /*purple*/,
    `rgba(0,128,128,${opacity})` /*teal*/, `rgba(0,0,128,${opacity})` /*navy*/, `rgba(138,57,0,${opacity})` /*brown*/, `rgba(205,133,63,${opacity})`,
    `rgba(244,164,96,${opacity})`, `rgba(139,105,30,${opacity})`, `rgba(165,42,42,${opacity})`, `rgba(178,34,34,${opacity})`,
    `rgba(220,20,60,${opacity})`, `rgba(255,140,0,${opacity})`, `rgba(255,165,0,${opacity})`, `rgba(255,215,0,${opacity})`, `rgba(184,134,11,${opacity})`,
    `rgba(218,165,32,${opacity})`, `rgba(218,165,32,${opacity})`, `rgba(238,232,170,${opacity})`, `rgba(189,183,107,${opacity})`, `rgba(240,230,140,${opacity})`,
    `rgba(0,100,0,${opacity})`, `rgba(34,139,34,${opacity})`, `rgba(32,178,170,${opacity})`, `rgba(47,79,79,${opacity})`,
    `rgba(0,139,139,${opacity})`, `rgba(95,158,160,${opacity})`, `rgba(70,130,180,${opacity})`, `rgba(25,25,112,${opacity})`,
    `rgba(0,0,128,${opacity})`, `rgba(0,0,139,${opacity})`, `rgba(72,61,139,${opacity})`, `rgba(75,0,130,${opacity})`, `rgba(139,0,139,${opacity})`,
    `rgba(0,0,0,${opacity})`, `rgba(105,105,105,${opacity})`, `rgba(169,169,169,${opacity})`];

    if (isRandom)
    {
      let index = Math.floor(this.getRandomNumber(0, colors.length - 1));
      let color = colors[index];
      return { color: color, index: index };
    } else
      //if specific
      {
        if (index >= 0 && index < colors.length)
        {
          return colors[index];
        }
        return colors[0];
      }
  }
  getVelocity()
  {
    let x, y;
    //flip a coin to decide if gridworm moves vertically or horizontally
    if (Math.random() > 0.5) //if gridworm moves vertically
      {
        x = 0; //no horizontal movement
        y = Math.random() > 0.5 ? -this.speed : this.speed; //flip a coin to decide if gridworm moves upwards or downwards
      } else
      //if gridworm moves horizontally
      {
        x = Math.random() > 0.5 ? -this.speed : this.speed; //flip a coin to decide if gridworm moves left or right
        y = 0; //no vertical movement
      }
    return { x: x, y: y };
  }
  /**
    * Returns a random number between min (inclusive) and max (exclusive)
    * @param  {number} min The lesser of the two numbers. 
    * @param  {number} max The greater of the two numbers.  
    * @return {number} A random number between min (inclusive) and max (exclusive)
    */
  getRandomNumber(min, max)
  {
    return Math.random() * (max - min) + min;
  }
  drawCircle(x, y, circleradius, ctx, colorIndex)
  {
    for (let i = 0; i < 3; i++)
    {
      let color = '';
      let radius = 0;
      switch (i) {//create three circles with same center

        case 0:
          radius = circleradius; //smallest circle
          color = this.getColor(1, false, colorIndex);
          break;
        case 1:
          radius = circleradius * 2; //bigger circle 
          color = this.getColor(0.5, false, colorIndex);
          break;
        case 2:
          radius = circleradius * 6; //biggest circle 
          color = this.getColor(0.2, false, colorIndex);
          break;}

      //draw the node
      ctx.beginPath();
      ctx.arc(x, y, radius, 0, 2 * Math.PI);
      ctx.fillStyle = color;
      ctx.fill();
      ctx.strokeStyle = color;
      ctx.stroke();
    }
  }
  drawArrowHead(x, y, circleradius, ctx, colorIndex)
  {
    let points = [];
    if (this.velocity.x === 0) //if gridworm is moving vertically
      {
        if (this.velocity.y > 0) //if gridworm is moving down
          {
            points.push({ x: x + this.interval / 3, y: y }); //point to the right
            points.push({ x: x - this.interval / 3, y: y }); //point to the left 
            points.push({ x: x, y: y + this.interval / 3 }); //point below 
          } else
          //if gridworm is moving up
          {
            points.push({ x: x + this.interval / 3, y: y }); //point to the right
            points.push({ x: x - this.interval / 3, y: y }); //point to the left
            points.push({ x: x, y: y - this.interval / 3 }); //point above  
          }
      } else
      //if gridworm is moving horizontally
      {
        if (this.velocity.x > 0) //if gridworm is moving right
          {
            points.push({ x: x + this.interval / 3, y: y }); //point to the right 
            points.push({ x: x, y: y - this.interval / 3 }); //point above
            points.push({ x: x, y: y + this.interval / 3 }); //point below 
          } else
          //if gridworm is moving left
          {
            points.push({ x: x - this.interval / 3, y: y }); //point to the left
            points.push({ x: x, y: y - this.interval / 3 }); //point above
            points.push({ x: x, y: y + this.interval / 3 }); //point below 
          }
      }
    //draw a circle about the points that make the arrow head
    for (let i = 0; i < points.length; i++)
    {
      let point = points[i];
      this.drawCircle(point.x, point.y, circleradius / 2, ctx, colorIndex);
    }
    this.drawTriangle(points[0], points[1], points[2], ctx); //draw the arrow head 
  }
  drawTriangle(point1, point2, point3, ctx)
  {
    ctx.beginPath();
    ctx.moveTo(point1.x, point1.y);
    ctx.lineTo(point2.x, point2.y);
    ctx.lineTo(point3.x, point3.y);
    ctx.fillStyle = 'rgba(0,0,0,0.1)'; //transparent black  
    ctx.fill();
  }
  draw(ctx)
  {
    //draw the head of the gridworm 
    this.drawCircle(this.xCoord, this.yCoord, this.radius / 2, ctx, this.mainColorIndex);
    this.drawArrowHead(this.xCoord, this.yCoord, this.radius / 2, ctx, this.arrowHeadColorIndex);
    //draw circles and squares at every visited junctions in the gridworm's memory(not RAM)
    for (let i = 0; i < this.junctionMemory.length; i++)
    {
      let junction = this.junctionMemory[this.junctionMemory.length - (i + 1)];
      //draw a circle at each junction point
      this.drawCircle(junction.point.x, junction.point.y, this.radius / 2, ctx, this.mainColorIndex);
      //draw painted squares at every junction point
      ctx.fillStyle = this.getColor(0.1, false, this.mainColorIndex);
      ctx.fillRect(junction.point.x, junction.point.y, this.interval, this.interval);

    }
    //draw the line connecting head to body
    ctx.strokeStyle = 'black';
    ctx.lineWidth = this.radius;
    ctx.beginPath();
    ctx.moveTo(this.xCoord, this.yCoord);
    //draw a line to link all the visited junctions in the gridworm's memory(not RAM)
    for (let i = 0; i < this.junctionMemory.length; i++)
    {//starting from the most recent to the least recent(LIFO)[NB: more like a stack data structure]
      let junction = this.junctionMemory[this.junctionMemory.length - (i + 1)];
      ctx.lineTo(junction.point.x, junction.point.y);
    }
    ctx.stroke();
    ctx.closePath();
  }
  update(deltaTime)
  {
    this.junctionMemoryLength = this.junctionMemoryLength < 1 ? 1 : this.junctionMemoryLength;
    //keep the gridworm moving in its current direction  
    this.xCoord += this.velocity.x; //if gridworm is going left or right, keep it going
    this.yCoord += this.velocity.y; //if gridworm is going up or down, keep it going   
    if (this.xCoord <= this.interval) //if gridworm reaches the leftmost point 
      {
        this.xCoord = this.interval;
        this.velocity.x = -this.velocity.x; //move right 
        this.xCoord += this.velocity.x * 3; //nudge it a bit away from the edge
      }
    if (this.xCoord >= this.screenWidth - this.interval) //if gridworm reaches the rightmost point
      {
        this.xCoord = this.junctionMemory[this.junctionMemory.length - 1].point.x;
        this.velocity.x = -this.velocity.x; //move left 
        this.xCoord += this.velocity.x * 3; //nudge it a bit away from the edge
      }
    if (this.yCoord <= this.interval) //if gridworm reaches the topmost most point
      {
        this.yCoord = this.interval;
   .........完整代码请登录后点击上方下载按钮下载查看

网友评论0