JavaScript+canvas实现粒子动画效果

1.HTML部分

DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>粒子效果title>
    <style>
      canvas {
        position: fixed;
        left: 0;
        top: 0;
        background: #222;
      }
    style>
  head>

  <body>
    <canvas>canvas>
    <script src="./js/canvas.js">script>
  body>
html>

2.JavaScript部分

const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d');
cvs.width = window.innerWidth * window.devicePixelRatio;
cvs.height = window.innerHeight * window.devicePixelRatio;

/**
 * 获取[min, max]范围内的随机整数
 * @param {number} min
 * @param {number} max
 * @return {number}
 */
function getRandom(min, max) {
  return Math.floor(Math.random() * (max + 1 - min) + min);
}

class Point {
  constructor() {
    this.r = 6;
    this.x = getRandom(0, cvs.width - this.r / 2);
    this.y = getRandom(0, cvs.height - this.r / 2);
    this.xSpeed = getRandom(-100, 100);
    this.ySpeed = getRandom(-100, 100); // 每秒钟移动的速度
    // 记录上一次作画的时间 - 知道每一个小段时间的间隔, 计算出移动距离
    this.lastDrawTime = null;
  }
  draw() {
    // 更新坐标
    if (this.lastDrawTime) {
      // 计算新的坐标
      const duration = (Date.now() - this.lastDrawTime) / 1000;
      // 距离
      const xDis = this.xSpeed * duration,
        yDis = this.ySpeed * duration;

      // 计算出新的x和y的坐标
      let x = this.x + xDis,
        y = this.y + yDis;

      // 判断边界
      if (x > cvs.width - this.r / 2) {
        x = cvs.width - this.r / 2;
        this.xSpeed = -this.xSpeed; // 正的变负的 负的变正的
      } else if (x < 0) {
        x = 0;
        this.xSpeed = -this.xSpeed;
      }

      if (y > cvs.height - this.r / 2) {
        y = cvs.height - this.r / 2;
        this.ySpeed = -this.ySpeed; // 正的变负的 负的变正的
      } else if (y < 0) {
        y = 0;
        this.ySpeed = -this.ySpeed;
      }

      this.x = x;
      this.y = y;
    }
    ctx.beginPath();
    // 画一个圆
    ctx.arc(this.x, this.y, 3, 0, 2 * Math.PI);
    ctx.fillStyle = 'rgba(200, 200, 200, 0.8)';
    ctx.fill();
    this.lastDrawTime = Date.now();
  }
}

class Graph {
  /**
   *
   * @param {number} pointNumber 点的个数
   * @param {number} maxDis 两个点直接的最大距离
   */
  constructor(pointNumber = 100, maxDis = 200) {
    // 生成一系列的点
    this.points = new Array(pointNumber).fill(0).map(() => new Point());
    this.maxDis = maxDis;
  }
  draw() {
    requestAnimationFrame(() => {
      this.draw();
    });
    ctx.clearRect(0, 0, cvs.width, cvs.height);
    for (let i = 0; i < this.points.length; i++) {
      const p1 = this.points[i];
      p1.draw();
      // 跟后面的点相连
      for (let j = i + 1; j < this.points.length; j++) {
        const p2 = this.points[j];
        ctx.beginPath();
        ctx.moveTo(p1.x, p1.y);
        ctx.lineTo(p2.x, p2.y);
        ctx.closePath();
        // 利用勾股定理计算出两个点之间的距离  **是指数运算符 Math.sqrt()开根号
        const d = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
        if (d > this.maxDis) {
          continue; // 看下一个点
        }
        ctx.strokeStyle = `rgba(200, 200, 200, ${1 - d / this.maxDis})`;
        ctx.stroke();
      }
      // 两个点它们的距离越远, 颜色就越透明, 越近颜色就越不透明
      // 让点运动起来
    }
  }
}

// 画直线
// ctx.beginPath()
// ctx.moveTo(100, 50)
// ctx.lineTo(200, 100)
// ctx.closePath()
// ctx.strokeStyle = '#fff'
// // 描边
// ctx.stroke()

// ctx.beginPath()
// // 画一个圆
// ctx.arc(100, 50, 6, 0, 2 * Math.PI)
// ctx.fillStyle = '#fff'
// ctx.fill()

// ctx.beginPath()
// // 画一个圆
// ctx.arc(200, 100, 6, 0, 2 * Math.PI)
// ctx.fillStyle = '#fff'
// ctx.fill()

// const p1 = new Point()
// const p2 = new Point()
// p1.draw()
// p2.draw()

const g = new Graph();
g.draw();

JavaScript+canvas实现粒子动画效果_第1张图片

你可能感兴趣的:(javascript,开发语言,ecmascript,canvas)