canvas实现水母游动可交互跟随鼠标动画效果代码

代码语言:html

所属分类:动画

代码描述:canvas实现水母游动可交互跟随鼠标动画效果代码

代码标签: canvas 水母 游动 交互 跟随 鼠标 动画

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

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">

<style>
    html, body {
  width:  100%;
  height: 100%;
  margin: 0;
  background: rgb(0,30,60);
  overflow: hidden;
}

#C{
}
</style>
</head>

<body>
    <!-- partial:index.partial.html -->
    <canvas id="C"></canvas>
    <!-- partial -->
    <script >
        
        window.onload = function () {
  let ctx = document.getElementById("C"),
    c = ctx.getContext("2d"),
    w,
    h;
  fitCanvas();

  function limit(vec, b) {
    this.d = Math.sqrt(Math.pow(vec.x, 2) + Math.pow(vec.y, 2));
    this.ang = Math.atan2(vec.y, vec.x);
    if (this.d > b) {
      return {
        x: b * Math.cos(this.ang),
        y: b * Math.sin(this.ang)
      };
    } else {
      return {
        x: this.d * Math.cos(this.ang),
        y: this.d * Math.sin(this.ang)
      };
    }
  }
  function setmag(a, m) {
    this.ang = Math.atan2(a.y, a.x);
    return {
      x: m * Math.cos(this.ang),
      y: m * Math.sin(this.ang)
    };
  }

  let mouse = { x: false, y: false },
    last_mouse = {},
    pi = Math.PI,
    seaMargin = 1000,
    boids = new Array(100);

  class boid {
    constructor() {
      this.opacity = Math.random() * 0.5 + 0.05;
      this.ang = Math.random() * 2 * Math.PI;
      this.mf = 0.1;
      this.ms = Math.random() * 0.1 + 0.9;
      this.vm = Math.random() * 1 + 0.5;
      this.pos = {
        x: Math.random() * w,
        y: Math.random() * h
      };
      this.vel = {
        x: this.vm * Math.cos(this.ang),
        y: this.vm * Math.sin(this.ang)
      };
      this.acc = {
        x: 0,
        y: 0
      };
    }
    flock(other) {
      this.aa = {
        x: 0,
        y: 0
      };
      this.ap = {
        x: 0,
        y: 0
      };
      this.as = {
        x: 0,
        y: 0
      };
      this.count = 0;
      for (var ot of other) {
        if (ot != this) {
          this.dis = Math.sqrt(
            Math.pow(ot.pos.x - this.pos.x, 2) +
              Math.pow(ot.pos.y - this.pos.y, 2)
          );
          if (this.dis < 40) {
            this.aa.x += ot.vel.x;
            this.aa.y += ot.vel.y;
            this.ap.x += ot.pos.x;
            this.ap.y += ot.pos.y;
            this.as.x += this.pos.x - ot.pos.x;
            this.as.y += this.pos.y - ot.pos.y;
            this.count++;
          }
        }
      }
      if (this.count != 0) {
        this.aa.x /= this.count;
        this.aa.y /= this.count;
        this.ap.x /= this.count;
        this.ap.y /= this.count;
        this.as.x /= this.count;
        this.as.y /= this.count;

        this.as = setmag(
          this.as,
          4 / Math.sqrt(Math.pow(this.as.x, 2) + Math.pow(this.as.y, 2))
        );

        this.aa.x -= this.vel.x;
        this.aa.y -= this.vel.y;
        this.ap.x -= this.vel.x;
        this.ap.y -= this.vel.y;
      }

      this.aa = limit(this.aa, this.mf);
      this.ap = limit(this.ap, this.mf);
      this.as = limit(this.as, 4 * this.mf);
    }
    move() {
      this.acc = {
        x: 0,
        y: 0
      };

      this.acc.x += this.aa.x;
      this.acc.y += this.aa.y;
      this.acc.x += this.ap.x;
      this.acc.y += this.ap.y;
      this.acc.x += this.as.x;
      this.acc.y += this.as.y;
      this.pos.x += this.vel.x;
      this.pos.y += this.vel.y;
      this.vel.x += this.acc.x;
      this.vel.y += this.acc.y;

      this.vel = limit(this.vel, this.ms);
      this.ang = Math.atan2(this.vel.y, this.vel.x);

      if (this.pos.x > w + seaMargin) {
        this.pos.x -= w + seaMargin;
      }
      if (this.pos.x < -seaMargin) {
        this.pos.x += w + seaMargin;
      }
      if (this.pos.y > h + seaMargin) {
        this.pos.y -= h + seaMargin;
      }
      if (this.pos.y < -seaMargin) {
        this.pos.y += h + seaMargin;
      }
    }
    show() {
      c.beginPath();
      c.lineTo(
        this.pos.x - this.opacity * 20 * Math.cos(this.ang),
        this.pos.y - this.opacity * 20 * Math.sin(this.ang)
      );
      c.lineTo(
        this.pos.x + this.opacity * 20 * Math.cos(this.ang),
        this.pos.y + this.opacity * 20 * Math.sin(this.ang)
      );
      c.strokeStyle = "rgba(255,255,255," + this.opacity + ")";
      c.lineWidth = this.opacity * 8;
      c.lineCap = "round";
      c.stroke();
    }
  }

  class node {
    constructor(x, y, size, index, length) {
      this.x = x;
      this.y = y;
      this.size = size;
      this.angle = Math.random() * 2 * Math.PI;
      this.nx = this.x + size * 2 * Math.cos(this.angle);
      this.ny = this.y + size * 2 * Math.sin(this.angle);
      this.i = index;
      this.l = length;
    }
    follow(m) {
      this.errx = m.x - this.x;
      this.erry = m.y - this.y;
      this.td = Math.sqrt(Math.pow(this.errx, 2) + Math.pow(this.erry, 2));
      this.ta = Math.atan2(this.erry, this.errx);
      this.x = this.x + this.td * 0.2 * Math.cos(this.ta);
      this.y = this.y + this.td * 0.2 * Math.sin(this.ta);
    }
    update(other, r) {
      this.errx = other.x - this.x;
      this.erry = other.y - this.y;
      this.a = Math.atan2(this.erry, this.errx);
      this.nx = this.x + r * Math.cos(this.a);
      this.ny = this.y + r * Math.sin(this.a);
    }
    avoid(other, rad) {
      this.d = Math.sqrt(
        Math.pow(other.x - this.x, 2) + Math.pow(other.y - this.y, 2)
      );
      this.ang = Math.atan2.........完整代码请登录后点击上方下载按钮下载查看

网友评论0