Step 1: 创立一个 HTML 文件并设置一个画布

首要,咱们需要在 HTML 文件中创立一个画布。咱们能够运用 元素或 元素创立它,并为其设置一些根本款式。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Fireworks Animation</title>
    <style>
      canvas {
        width: 100%;
        height: 100%;
        background-color: #000;
      }
    </style>
  </head>
  <body>
    <canvas></canvas>
    <script src="app.js"></script>
  </body>
</html>

Step 2: 创立画布上下文

接着,咱们将创立画布的上下文用于在画布上制作咱们的焰火。

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

Step 3: 制作焰火

现在,咱们将开端制作焰火。咱们将运用一些简略的绘图API来创立圆形和线条,并运用一些数学计算来决议焰火的运动途径和形状。

在此示例中,咱们将创立一个名为“Firework”的目标,该目标包含有关焰火的所有信息。每次咱们制作焰火时,咱们将创立一个新的“Firework”目标。

class Firework {
  constructor() {
    this.x = canvas.width / 2;
    this.y = canvas.height;
    this.speed = Math.random() * 5 + 5;
    this.angle = Math.random() * Math.PI * 2;
    this.vx = Math.sin(this.angle) * this.speed;
    this.vy = Math.cos(this.angle) * this.speed * -1;
    this.color = `hsla(${Math.random() * 360}, 100%, 50%, 1)`;
    this.brightness = Math.random() * 80 + 20;
    this.radius = Math.random() * 2 + 2;
    this.life = false;
  }
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
  }
  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.vy += 0.1;
    this.radius -= 0.05;
    this.brightness -= 2;
    if (this.brightness < 0) {
      this.life = true;
    }
  }
}

我将解释一下Firework目标中的每个特点和办法。

  1. this.xthis.y存储焰火的当时方位。
  2. this.speed 是它的速度
  3. this.angle 是焰火的发射角度。咱们将它随机设置为 Math.PI * 2 , 这使焰火能在任何方向上飞翔。
  4. 经过运用 Math.sin()Math.cos() 来将速度转换为X和Y轴上的速度 this.vxthis.vy
  5. 还有一个随机色彩this.color,和一个随机大小的this.radius
  6. this.brightness用于储存焰火的当时亮度,并随时间推移削减,以使焰火逐步消失,使动画愈加逼真。
  7. 当焰火的 this.brightness 削减到接近零时,咱们将 this.life 设置为 true ,表示焰火能够被销毁并从目标数组中删去。

draw()办法中,咱们运用 ctx.beginPath() 开端制作焰火,并在其中心创立一个圆形,然后填充它的色彩。

update()办法中,咱们移动焰火的当时方位,使其“爆炸”并削减亮度。

Step 4: 创立一个焰火环境

现在,咱们将创立一个包含多个焰火目标的环境,并使其依照特定的频率和规则发生爆炸。

const fireworks = [];
function createFirework() {
  const x = Math.random() * canvas.width;
  const y = canvas.height;
  const firework = new Firework();
  firework.x = x;
  fireworks.push(firework);
}
setInterval(createFirework, 100);
function animate() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  fireworks.forEach((firework, index) => {
    firework.draw();
    firework.update();
    if (firework.life) {
      fireworks.splice(index, 1);
    }
  });
  requestAnimationFrame(animate);
}
animate();

首要,咱们将手动创立一个名为fireworks的空数组以存储多个Firework目标。

接下来,咱们创立一个名为 createFirework()的函数,该函数将在特定距离内创立随机方位的焰火。在这种情况下,咱们将每100毫秒创立一次焰火。

animate()函数中,咱们首要运用 ctx.fillStyle 铲除画布,并在其中创立一个半透明的黑色矩形。这有助于创立动画作用。

然后,咱们遍历 fireworks 数组中的每个 Firework 目标,并顺次调用其 draw()update() 办法。假如焰火能够从数组中删去,则将其删去。

最终,咱们运用 requestAnimationFrame()animate() 函数设为递归,这样它将每帧履行一次,从而创造出流畅而美丽的动画作用。

完整代码:

class Firework {
  constructor() {
    this.x = canvas.width / 2;
    this.y = canvas.height;
    this.speed = Math.random() * 5 + 5;
    this.angle = Math.random() * Math.PI * 2;
    this.vx = Math.sin(this.angle) * this.speed;
    this.vy = Math.cos(this.angle) * this.speed * -1;
    this.color = `hsla(${Math.random() * 360}, 100%, 50%, 1)`;
    this.brightness = Math.random() * 80 + 20;
    this.radius = Math.random() * 2 + 2;
    this.life = false;
  }
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
  }
  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.vy += 0.1;
    this.radius -= 0.05;
    this.brightness -= 2;
    if (this.brightness < 0) {
      this.life = true;
    }
  }
}
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const fireworks = [];
function createFirework() {
  const x = Math.random() * canvas.width;
  const y = canvas.height;
  const firework = new Firework();
  firework.x = x;
  fireworks.push(firework);
}
setInterval(createFirework, 100);
function animate() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  fireworks.forEach((firework, index) => {
    firework.draw();
    firework.update();
    if (firework.life) {
      fireworks.splice(index, 1);
    }
  });
  requestAnimationFrame(animate);
}
animate();