前端小盖的博客
欢迎来到前端小盖的博客

线条canvas 鼠标连接 附近点效果

代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>canvasLine</title>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <style>
      body {
        overflow: hidden;
        margin: 0;
        background-color: rgb(70, 70, 70);
      }
      #canvas {
        opacity: 0.5;
      }
    </style>
  </body>

  <script>
    (function () {
      const canvas = document.getElementById("canvas");
      const ctx = canvas.getContext("2d");
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      const particleNum = 100; // 粒子数量 100
      const lineDistance = 130; // 连线距离
      const colorRgb = "254, 250, 224"; // 粒子颜色
      let particles = []; // 粒子数组
      let interactionParticle = null; // 当前交互粒子
      class Particle {
        constructor(x, y, velocityX, velocityY, size, color) {
          // 位置
          this.x = x;
          this.y = y;
          // 速度 正负为方向
          this.velocityX = velocityX;
          this.velocityY = velocityY;
          this.size = size;
          this.color = color;
        }

        draw() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
          ctx.fillStyle = this.color;
          ctx.fill();
        }
        update() {
          if (this.x < 0 || this.x > canvas.width) {
            this.velocityX *= -1;
          }
          if (this.y < 0 || this.y > canvas.width) {
            this.velocityY *= -1;
          }
          this.x += this.velocityX;
          this.y += this.velocityY;
          this.draw();
        }
      }

      function getRandomArbitrary(min, max) {
        return Math.random() * (max - min) + min;
      }

      function createParticles() {
        for (
          let i = 0;
          i < parseInt((canvas.width * canvas.height) / 5600);
          i++
        ) {
          const size = getRandomArbitrary(1, 2);

          const x = getRandomArbitrary(0, canvas.width);
          const y = getRandomArbitrary(0, canvas.height);
          const velocityX = getRandomArbitrary(-1, 1);
          const velocityY = getRandomArbitrary(-1, 1);
          let color = `rgba(${colorRgb}, ${1 - size / 2})`;
          particles.push(new Particle(x, y, velocityX, velocityY, size, color));
        }
      }

      function connect() {
        if (!interactionParticle) {
          // ctx.clearRect(0, 0, canvas.width, canvas.height);
          return;
        }
        for (let i = 0; i < particles.length; i++) {
          for (let j = i + 1; j < particles.length; j++) {
            const interactionParticlecur = interactionParticle;
            const dxi = particles[i].x - interactionParticlecur.x;
            const dyi = particles[i].y - interactionParticlecur.y;
            const dxj = particles[j].x - interactionParticlecur.x;
            const dyj = particles[j].y - interactionParticlecur.y;
            const dx = particles[i].x - particles[j].x;
            const dy = particles[i].y - particles[j].y;
            const distance = Math.sqrt(dx * dx + dyj * dyj);
            const distancei = Math.sqrt(dxi * dxi + dyi * dyi);
            const distancey = Math.sqrt(dxj * dxj + dyj * dyj);
            if (distancei <= lineDistance && distancey <= lineDistance) {
              ctx.strokeStyle = `rgba(${colorRgb}, ${
                1 -
                (distance + 10 >= lineDistance
                  ? 1
                  : (distance + 10) / lineDistance)
              })`;
              ctx.beginPath();
              ctx.lineWidth = 0.5;
              ctx.moveTo(particles[i].x, particles[i].y);
              ctx.lineTo(particles[j].x, particles[j].y);
              ctx.stroke();
            }
          }
        }
      }

      function animate() {
        requestAnimationFrame(animate);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        particles.forEach((particle) => {
          particle.update();
        });
        connect();
      }

      function bindEvents() {
        window.addEventListener("resize", () => {
          canvas.width = window.innerWidth;
          canvas.height = window.innerHeight;
          particles = [];
          interactionParticle = null;
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          createParticles();
        });
        canvas.addEventListener("mouseover", (e) => {
          console.log("interactionParticle", interactionParticle);
          if (!interactionParticle) {
            interactionParticle = new Particle(
              e.x,
              e.y,
              0,
              0,
              2,
              `rgba(${colorRgb}, 0.3)`
            );
            particles.push(interactionParticle);
          }
        });
        canvas.addEventListener("mousemove", (e) => {
          console.log("interactionParticle-mousemove", interactionParticle);
          interactionParticle.x = e.x;
          interactionParticle.y = e.y;
        });
        canvas.addEventListener("mouseout", () => {
          interactionParticle.x = -100;
          interactionParticle.y = -100;
        });
      }
      bindEvents();
      createParticles();
      animate();
    })();
  </script>
</html>

效果:

posted @ 2025-06-06 17:34  前端小盖  阅读(10)  评论(0)    收藏  举报