HTML Canvas particle animation

Ming Sun

Ming Sun / May 07, 2023

4 min read––– views

React component

import { useEffect } from "react";

const CanvasAnimation = () => {
  useEffect(() => {
    let canvasParent = document.getElementById("canvasParent");
    let canvas = document.getElementById("canvas1");
    let ctx = canvas.getContext("2d");
    canvas.width = canvasParent.offsetWidth;
    canvas.height = 400;
    let particleArray = [];
    let hue = 0;

    let mouse = { x: undefined, y: undefined };

    canvas.addEventListener("mousemove", function (event) {
      mouse.x = event.offsetX;
      mouse.y = event.offsetY;

      for (let i = 0; i < 2; i++) {
        particleArray.push(new Particle());
      }
    });

    class Particle {
      constructor() {
        this.x = mouse.x;
        this.y = mouse.y;
        // this.x = Math.random() * canvas.width;
        // this.y = Math.random() * canvas.height;
        this.radius = Math.random() * 15 + 1;
        this.speed = 5;
        this.speedX = (Math.random() - 0.5) * this.speed;
        this.speedY = (Math.random() - 0.5) * this.speed;
        this.color = "hsl(" + hue + ",100%,50%)";
      }

      update() {
        this.x += this.speedX;
        this.y += this.speedY;
        if (this.x < 0 || this.x > canvas.width) {
          this.speedX *= -1;
        }

        if (this.y < 0 || this.y > canvas.height) {
          this.speedY *= -1;
        }

        if (this.radius > 0.2) this.radius -= 0.1;
      }

      draw() {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
        ctx.fill();
      }
    }

    function handleParticles() {
      for (let i = 0; i < particleArray.length; i++) {
        particleArray[i].update();
        particleArray[i].draw();

        for (let j = i; j < particleArray.length; j++) {
          let x1 = particleArray[i].x;
          let y1 = particleArray[i].y;
          let x2 = particleArray[j].x;
          let y2 = particleArray[j].y;
          let distance = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
          if (distance < 100) {
            ctx.beginPath();
            ctx.strokeStyle = particleArray[i].color;
            ctx.lineWidth = 0.2;
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.closePath();
            ctx.stroke();
          }
        }

        if (particleArray[i].radius <= 0.3) {
          particleArray.splice(i, 1);
          i--;
        }
      }
    }

    function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = "rgb(0,0,0)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      handleParticles();
      hue++;

      requestAnimationFrame(animate);
    }

    animate();
  }, []);

  return (
    <div id="canvasParent" className="w-full">
      <canvas id="canvas1"></canvas>
    </div>
  );
};

export default CanvasAnimation;

References and downloads

[1] HTML5 Canvas CRASH COURSE for Beginners


HomeWikis
SnippetsAbout
Google ScholarLinkedIn