Skip to content

02 粒子漂移

在深色舞台上铺满漂移的圆点,碰到边缘从对面回来。指针这一章仍然什么都不做。

src/scene/loop.js 里已经会对 particles 调用 particle.step() / particle.draw()。你要做的是加上粒子类型、填满数组,并在 boot() 里启动。

对照扩展里 skeletonparticles 的 Diff,再按下面的文件补全。

1. 新建 src/particle/particle.js

创建 src/particle/ 和这个文件:

js
import { canvas, ctx } from "../scene/canvas.js";

/** One drifting dot on the canvas. */
export class Particle {
  /**
   * Places the particle at a random position with a small velocity.
   */
  constructor() {
    this.x = Math.random() * canvas.width;
    this.y = Math.random() * canvas.height;
    this.vx = (Math.random() - 0.5) * 3.8;
    this.vy = (Math.random() - 0.5) * 3.8;
    this.radius = 1.6 + Math.random() * 2.2;
  }

  /**
   * Advances position and wraps at the canvas edges.
   */
  step() {
    this.x += this.vx;
    this.y += this.vy;
    this.wrap();
  }

  /**
   * Wraps this particle to the opposite edge when it leaves the canvas.
   */
  wrap() {
    if (this.x < 0) {
      this.x += canvas.width;
    } else if (this.x > canvas.width) {
      this.x -= canvas.width;
    }
    if (this.y < 0) {
      this.y += canvas.height;
    } else if (this.y > canvas.height) {
      this.y -= canvas.height;
    }
  }

  /**
   * Draws this particle as a filled circle.
   */
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = "#c9d7ff";
    ctx.fill();
  }
}

2. 新建 src/particle/field.js

同一目录。改写已有的 particles 数组,不要重新声明它:

js
import { Particle } from "./particle.js";
import { particles } from "../scene/loop.js";

/**
 * Replaces the particle field with a new random set.
 */
export function createParticles() {
  particles.length = 0;
  for (let i = 0; i < 90; i += 1) {
    particles.push(new Particle());
  }
}

3. src/main.js — 从 boot() 启动粒子场

在文件顶部、现有的 frame / resize import 上面增加:

js
import { createParticles } from "./particle/field.js";

boot() 里,resize(); 之后frame(); 之前加上:

js
createParticles();

不要删掉 boot()frame() 调用。

验收

http:// 打开。浅色小点在画布上滑过,从对面边缘再出现。移动鼠标不应改变任何东西。

下一章:跟随光标