鼠标粒子跟随动画

前言

本文将详细介绍如何使用JavaScript和Canvas实现一个简单的粒子动画效果。在实现粒子动画效果之前,我们需要了解一些基本的概念。粒子动画效果,本质上是通过一组粒子的运动来实现的。每个粒子都有自己的位置、速度、加速度、颜色、大小和寿命等属性。在动画过程中,每个粒子的状态都会不断地更新,通过Canvas绘图API将粒子绘制到画布上,从而实现整个动画效果。

鼠标粒子跟随动画

基本架构

定义一个画布元素,并对画布及body样式初定义。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>鼠标粒子跟随动画</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>
</body>
</html>

功能实现

1. 获取 canvas 元素和上下文

在JavaScript中,我们可以使用document.getElementById方法获取指定ID的元素,然后使用该元素的getContext方法获取画布的上下文对象。在本例中,我们获取了ID为canvas的元素,并使用2D上下文进行绘图。

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

接下来,我们需要设置画布的宽高,使其与浏览器窗口大小相同。

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

2. 创建粒子类

我们创建了一个名为Particle的类,用于表示每个粒子的状态。在该类中,我们定义了粒子的位置、速度、加速度、颜色、大小和寿命等属性。同时,我们还实现了一个draw方法,用于将粒子绘制到画布上。

class Particle {
  constructor(x, y) {
    // 粒子的位置和速度
    this.x = x;
    this.y = y;
    this.vx = Math.random() * 2 - 1;
    this.vy = Math.random() * 2 - 1;
    // 粒子的加速度
    this.ax = 0;
    this.ay = 0;
    // 粒子的颜色、大小和寿命
    this.color = `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.random()})`;
    this.size = 4;
    this.life = 300;
  }

  // 绘制粒子
  draw() {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();
  }
}

在该类中,我们使用了Math.random方法生成了随机的位置、速度、加速度、颜色、大小和寿命等属性。在draw方法中,我们使用了Canvas绘图API中的arc方法绘制了一个圆形,该圆形的位置和大小等属性都是由粒子的属性决定的。

3. 创建粒子集合类

我们创建了一个名为ParticleCollection的类,用于管理多个粒子的状态。在该类中,我们定义了一个particles数组,用于存储所有的粒子对象。同时,我们还定义了一个maxParticles属性,用于限制粒子的数量。在该类中,我们实现了三个方法:

createParticles:用于创建新的粒子对象,并将其加入到particles数组中。如果particles数组中的粒子数量超过了maxParticles属性的限制,我们将删除最早创建的粒子对象。

updateParticles:用于更新所有粒子对象的状态。在该方法中,我们根据粒子的加速度更新其速度和位置,并减少其寿命。如果粒子的寿命为0,我们将从particles数组中删除该粒子对象。

drawParticles:用于将所有粒子对象绘制到画布上。在该方法中,我们遍历particles数组,依次调用每个粒子对象的draw方法。

class ParticleCollection {
  constructor() {
    // 粒子数组和最大粒子数
    this.particles = [];
    this.maxParticles = 300;
  }

  // 创建粒子
  createParticles(x, y, count) {
    for (let i = 0; i < count; i++) {
      // 如果粒子数量超过最大值,则删除最早创建的粒子
      if (this.particles.length >= this.maxParticles) {
        this.particles.shift();
      }
      // 创建新的粒子并加入数组中
      const particle = new Particle(x, y);
      this.particles.push(particle);
      // 3秒后删除该粒子
      setTimeout(() => {
        const index = this.particles.indexOf(particle);
        if (index !== -1) {
          this.particles.splice(index, 1);
        }
      }, 3000);
    }
  }

  // 更新粒子状态
  updateParticles() {
    for (let i = 0; i < this.particles.length; i++) {
      const particle = this.particles[i];
      // 根据粒子的加速度更新速度和位置
      particle.vx += particle.ax;
      particle.vy += particle.ay;
      particle.x += particle.vx;
      particle.y += particle.vy;
      // 减少粒子寿命
      particle.life -= 1;
      // 如果粒子寿命为0,则从数组中删除
      if (particle.life <= 0) {
        this.particles.splice(i, 1);
        i--;
      }
    }
  }

  // 绘制粒子
  drawParticles() {
    for (let i = 0; i < this.particles.length; i++) {
      const particle = this.particles[i];
      particle.draw();
    }
  }
}

在该类中,我们使用了setTimeout方法,用于在粒子的寿命结束后将其从particles数组中删除。在updateParticles方法中,我们使用了一个for循环遍历particles数组,依次更新每个粒子对象的状态。在 drawParticles方法中,我们同样使用了一个for循环遍历particles数组,依次绘制每个粒子对象。

4. 监听鼠标移动事件,创建粒子

我们使用addEventListener方法监听了鼠标移动事件。在事件回调函数中,我们调用了ParticleCollection类的 createParticles方法,用于创建新的粒子对象。在本例中,我们设置了每次创建5个粒子对象,并将粒子对象的位置设置为鼠标当前位置。

canvas.addEventListener('mousemove', e => {
  particleCollection.createParticles(e.clientX, e.clientY, 5);
});

5. 循环更新并绘制粒子

我们使用了一个名为loop的函数,用于不断地更新和绘制粒子对象。在该函数中,我们先清空画布,然后依次调用ParticleCollection类的updateParticles和drawParticles方法,更新和绘制所有粒子对象。最后,我们使用requestAnimationFrame方法循环调用loop函数,从而实现动画效果。

function loop() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  particleCollection.updateParticles();
  particleCollection.drawParticles();

  requestAnimationFrame(loop);
}

loop();

结语

通过以上操作,我们就可以使用JavaScript和Canvas实现一个简单的粒子动画效果。

原文链接:https://juejin.cn/post/7227062606041350204 作者:codePanda

(0)
上一篇 2023年4月30日 上午10:53
下一篇 2023年4月30日 上午11:03

相关推荐

发表评论

登录后才能评论