library / backgrounds / interactive-stars
live - 60fps 1920 x 1080
interactive-stars.html - self-contained
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Interactive Stars</title>
    <style>
      /*
        Interactive Stars
        -----------------
        This animation scatters stars across a dark sky and draws faint lines
        between those that are close together.  The mouse acts as a
        constellation generator: as you move, nearby stars connect to the
        cursor.  Stars drift slowly to add life to the scene.
      */
      html, body {
        margin: 0;
        padding: 0;
        height: 100%;
        overflow: hidden;
        background: linear-gradient(to bottom, #02021e, #08104d);
        cursor: crosshair;
      }
      canvas {
        display: block;
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <canvas id="stars"></canvas>
    <script>
      (function() {
        const canvas = document.getElementById('stars');
        const ctx    = canvas.getContext('2d');
        function resize() {
          canvas.width  = window.innerWidth;
          canvas.height = window.innerHeight;
        }
        window.addEventListener('resize', resize);
        resize();

        // Create star objects with random positions and small drift velocities.
        const starCount = 150;
        const stars = [];
        for (let i = 0; i < starCount; i++) {
          stars.push({
            x: Math.random() * canvas.width,
            y: Math.random() * canvas.height,
            r: Math.random() * 2 + 0.5,
            vx: (Math.random() - 0.5) * 0.1,
            vy: (Math.random() - 0.5) * 0.1
          });
        }

        // Track mouse for constellation effect.
        const mouse = { x: null, y: null };
        document.addEventListener('mousemove', (e) => {
          mouse.x = e.clientX;
          mouse.y = e.clientY;
        });
        document.addEventListener('mouseleave', () => {
          mouse.x = mouse.y = null;
        });

        function animate() {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          // Draw stars
          ctx.fillStyle = 'white';
          for (const s of stars) {
            s.x += s.vx;
            s.y += s.vy;
            // wrap around edges to create continuous motion
            if (s.x < 0) s.x += canvas.width;
            if (s.x > canvas.width) s.x -= canvas.width;
            if (s.y < 0) s.y += canvas.height;
            if (s.y > canvas.height) s.y -= canvas.height;
            ctx.beginPath();
            ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
            ctx.fill();
          }
          // Draw lines between nearby stars
          ctx.lineWidth = 0.5;
          for (let i = 0; i < starCount; i++) {
            for (let j = i + 1; j < starCount; j++) {
              const a = stars[i];
              const b = stars[j];
              const dx = a.x - b.x;
              const dy = a.y - b.y;
              const distSq = dx * dx + dy * dy;
              const threshold = 100 * 100;
              if (distSq < threshold) {
                const alpha = 1 - distSq / threshold;
                ctx.strokeStyle = `rgba(255, 255, 255, ${alpha * 0.3})`;
                ctx.beginPath();
                ctx.moveTo(a.x, a.y);
                ctx.lineTo(b.x, b.y);
                ctx.stroke();
              }
            }
          }
          // Draw lines to mouse
          if (mouse.x !== null) {
            for (const s of stars) {
              const dx = s.x - mouse.x;
              const dy = s.y - mouse.y;
              const distSq = dx * dx + dy * dy;
              const threshold = 120 * 120;
              if (distSq < threshold) {
                const alpha = 1 - distSq / threshold;
                ctx.strokeStyle = `rgba(255, 255, 255, ${alpha * 0.6})`;
                ctx.beginPath();
                ctx.moveTo(s.x, s.y);
                ctx.lineTo(mouse.x, mouse.y);
                ctx.stroke();
              }
            }
          }
          requestAnimationFrame(animate);
        }
        animate();
      })();
    </script>
  </body>
</html>

About this animation

Starfield that reacts to mouse movement.

Under the hood

Cursor-Repulsion Networking

A classic canvas starfield that reacts to the user's mouse. The script continuously maps a radius around the mouse pointer. If a star enters that radius, its velocity vector is temporarily inverted, causing it to flee from the user's cursor.

Source Code
Source copied
Partner hosting options for the copied effect:
Vercel Netlify Hostinger