数据可视化之路 - canvas 粒子背景效果

栏目: Html5 · 发布时间: 5年前

内容简介:之前的文章提到过 canvas 动画的难点和一般规则。canvas 采用了一种叫做本文我们做一个粒子动画效果看看:从图中可以看出,粒子运动效果依据以下规则:

之前的文章提到过 canvas 动画的难点和一般规则。canvas 采用了一种叫做 立即渲染模式 ,调用绘制方法后 canvas 会直接将图形绘制到画布上,然后就不再管它,canvas 也不会记住你绘制的任何图形。这和 dom 模型不同,我们始终可以在内存中获取到 dom 元素的引用。基于这种特点,我们在动画每一帧之前都会清除画布,重新绘制一遍。绘制步骤如下:

  1. 初始化图形的状态,如坐标、大小、速度,运动方向等
  2. 清除画布,根据图形状态调用绘制函数画图
  3. 更新图形状态,返回步骤 2

本文我们做一个粒子动画效果看看:

需求分析

从图中可以看出,粒子运动效果依据以下规则:

  1. 画布上有固定若干个粒子和线组成,一开始生成n个随机坐标的粒子
  2. 粒子朝随机方向固定速度运动,当触碰到画布边缘时回弹
  3. 鼠标移动到画布上时,会在鼠标位置生成一个粒子
  4. 当两个粒子直线距离小于一定距离时连线,否则不连线或取消连线

实现分析(不带代码)

  1. 为了记录粒子的坐标、速度、方向、连线等状态,并封装绘图方法,我们需要一个粒子类,为了绘制n个粒子,我们需要一个数组在存放粒子对象。首先将粒子类初始化,赋予随机的坐标并给定初始速度和初始方向。
  2. 往粒子数组内追加一个鼠标粒子对象,坐标为当前鼠标位置,监听鼠标滑动并更新鼠标粒子坐标。
  3. 每一帧我们会按速度和方向更新粒子对象的坐标并重绘画布,当监测粒子坐标超出画布时,给定粒子类一个相反的方向。
  4. 当检测到两个粒子距离小于一定距离时,连线。

代码解读

首先是粒子类,它接受一个渲染上下文作为参数,并封装了粒子的状态和绘图方法。

class Particle {
  ctx: CanvasRenderingContext2D;
  x: number;
  y: number;
  vx: number;
  vy: number;
  constructor(ctx: CanvasRenderingContext2D) {
    this.ctx = ctx;
    this.x = random(0, CANVAS_WIDTH);
    this.y = random(0, CANVAS_HEIGHT);
    this.vx = random(-VELOCITY, VELOCITY);
    this.vy = random(-VELOCITY, VELOCITY);
  }
  draw() {
    if (this.x > CANVAS_WIDTH || this.x < 0) {
      this.vx = -this.vx;
    }
    if (this.y > CANVAS_HEIGHT || this.y < 0) {
      this.vy = -this.vy;
    }
    this.x += this.vx;
    this.y += this.vy;
    this.ctx.beginPath();
    this.ctx.arc(this.x, this.y, PARTICLE_RADIUS, 0, Math.PI * 2);
    // this.ctx.closePath();
    this.ctx.fill();
  }
}
复制代码

其次是鼠标粒子,它接受渲染上下文和dom容器作为参数,和粒子类相同,并且监听容器的鼠标位置以更新其坐标。

class MouseParticle {
  ctx: CanvasRenderingContext2D;
  x = -1;
  y = -1;
  // 单例的
  static instance: MouseParticle;
  constructor(ctx: CanvasRenderingContext2D, container: HTMLCanvasElement) {
    this.ctx = ctx;
    if (MouseParticle.instance) return MouseParticle.instance;
    container.addEventListener("mouseenter", e => {
      this.x = e.clientX;
      this.y = e.clientY;
    });
    container.addEventListener("mousemove", e => {
      this.x = e.clientX;
      this.y = e.clientY;
    });
    container.addEventListener("mouseleave", e => {
      // 移到canvas外
      this.x = -1;
      this.y = -1;
    });
    MouseParticle.instance = this;
    return this;
  }
  draw() {
    this.ctx.beginPath();
    this.ctx.arc(this.x, this.y, PARTICLE_RADIUS, 0, Math.PI * 2);
    this.ctx.fill();
  }
}
复制代码

接着我们初始化粒子和鼠标粒子对象,并保存进粒子数组。

const particles: (Particle | MouseParticle)[] = [];
for (let index = 0; index < PARTICLE_COUNT; index++) {
  const particle = new Particle(ctx);
  particles.push(particle);
}
const mouseParticle = new MouseParticle(ctx, canvas);
复制代码

接下来是我们的主绘图函数,它会在每一帧调用,根据粒子的状态重绘画布。

function draw(ctx: CanvasRenderingContext2D) {
  requestAnimationFrame(() => draw(ctx));
  // 清除画布并重绘粒子
  ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
  particles.forEach(particle => {
    particle.draw();
  });
  // 重绘线
  ctx.save();
  particles.forEach(source => {
    particles.forEach(target => {
      const xDistance = Math.abs(source.x - target.x);
      const yDistance = Math.abs(source.y - target.y);
      const dis = Math.round(
        Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2))
      );
      if (dis < PARTICLE_DISTANCE) {
        ctx.globalAlpha = dis / PARTICLE_DISTANCE;
        ctx.beginPath();
        ctx.moveTo(source.x, source.y);
        ctx.lineTo(target.x, target.y);
        ctx.closePath();
        ctx.stroke();
      }
    });
  });
}
复制代码

在主绘图函数里我们遍历粒子数组,当两个粒子距离小于一定距离时连线。

完整的代码在这里

这样我们就完成一个粒子效果啦~~~


以上所述就是小编给大家介绍的《数据可视化之路 - canvas 粒子背景效果》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

代码整洁之道

代码整洁之道

[美]Robert C. Martin / 韩磊 / 人民邮电出版社 / 2010-1-1 / 59.00元

软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关。这一点,无论是敏捷开发流派还是传统开发流派,都不得不承认。 本书提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。作为编程领域的佼佼者,本书作者给出了一系列行之有效的整洁代码操作实践。这些实践在本书中体现为一条条规则(或称“启示”),并辅以来自现实项目的正、反两面的范例。只要遵......一起来看看 《代码整洁之道》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器