About this snippet

Design an interactive constellation background. We connected floating canvas orbs with dynamic lines that only appear when they drift close to each other, creating an intricate web of data.

Size
2.8 KB
Uses
HTML, CSS, JavaScript
Loads
Nothing external
Views
371
<div class="constellation-wrapper">
  <canvas id="constellation-canvas"></canvas>
  <div class="content-box">
    <h2>Global Network</h2>
    <p>A connected ecosystem that adapts in real time.</p>
  </div>
</div>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  margin: 0;
  background: #020617;
  overflow: hidden;
}

.constellation-wrapper {
  position: relative;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

#constellation-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

.content-box {
  position: relative;
  z-index: 2;
  text-align: center;
  color: #ffffff;
  pointer-events: none;
  background: rgba(15, 23, 42, 0.4);
  backdrop-filter: blur(8px);
  padding: 40px 60px;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.content-box h2 {
  font-size: 3rem;
  margin: 0 0 10px 0;
  letter-spacing: 2px;
}

.content-box p {
  font-size: 1.25rem;
  color: #94a3b8;
  margin: 0;
}
const canvas = document.getElementById("constellation-canvas");
const ctx = canvas.getContext("2d");

let width = window.innerWidth;
let height = window.innerHeight;
canvas.width = width;
canvas.height = height;

window.addEventListener("resize", function() {
  width = window.innerWidth;
  height = window.innerHeight;
  canvas.width = width;
  canvas.height = height;
});

const orbs = new Array();
const numOrbs = 70;

for (let i = 0; i < numOrbs; i++) {
  const orb = new Object();
  orb.x = Math.random() * width;
  orb.y = Math.random() * height;
  orb.vx = (Math.random() - 0.5) * 1;
  orb.vy = (Math.random() - 0.5) * 1;
  orb.radius = Math.random() * 2 + 1;
  orbs.push(orb);
}

function animate() {
  ctx.clearRect(0, 0, width, height);
  
  orbs.forEach(function(orb) {
    orb.x += orb.vx;
    orb.y += orb.vy;
    
    /* Bounce smoothly off walls */
    if (orb.x < 0 || orb.x > width) orb.vx *= -1;
    if (orb.y < 0 || orb.y > height) orb.vy *= -1;
    
    ctx.beginPath();
    ctx.arc(orb.x, orb.y, orb.radius, 0, Math.PI * 2);
    ctx.fillStyle = "#8b5cf6";
    ctx.fill();
  });
  
  /* Connect nearby orbs safely */
  orbs.forEach(function(orbA) {
    orbs.forEach(function(orbB) {
      const dx = orbA.x - orbB.x;
      const dy = orbA.y - orbB.y;
      const distance = Math.sqrt(dx * dx + dy * dy);
      
      if (distance > 0 && distance < 150) {
        ctx.beginPath();
        ctx.moveTo(orbA.x, orbA.y);
        ctx.lineTo(orbB.x, orbB.y);
        const alpha = 1 - (distance / 150);
        ctx.strokeStyle = "rgba(139, 92, 246, " + alpha + ")";
        ctx.lineWidth = 1;
        ctx.stroke();
      }
    });
  });
  
  window.requestAnimationFrame(animate);
}

animate();
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save