Floaters

Simple JS Floaters

Floaters

Thanks to Cluade.ai for knocking this out. Such a simple ask, but neither GPT or DeepSeek could figure it out. Great little coding test.


floaters.js

document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('animationCanvas');
const ctx = canvas.getContext('2d');

// Set canvas to full window size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Configuration
const config = {
circleCount: 120,
circleMinRadius: 2,
circleMaxRadius: 5,
circleColor: '#3498db',
lineColor: 'rgba(52, 152, 219, 0.5)',
minSpeed: 0.3,
maxSpeed: 0.8,
connectionDistance: 150  // Maximum distance for connection
};

// Circles array
let circles = [];

// Circle object
class Circle {
constructor() {
  this.radius = Math.random() * (config.circleMaxRadius - config.circleMinRadius) + config.circleMinRadius;
  this.x = Math.random() * canvas.width;
  this.y = Math.random() * canvas.height;
  this.speedX = (Math.random() - 0.5) * (config.maxSpeed - config.minSpeed) + config.minSpeed;
  this.speedY = (Math.random() - 0.5) * (config.maxSpeed - config.minSpeed) + config.minSpeed;
}

update() {
  // Move the circle
  this.x += this.speedX;
  this.y += this.speedY;

  // Bounce off edges
  if (this.x < this.radius || this.x > canvas.width - this.radius) {
    this.speedX = -this.speedX;
  }

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

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

// Initialize circles
function init() {
for (let i = 0; i < config.circleCount; i++) {
  circles.push(new Circle());
}
}

// Draw connections between circles
function drawConnections() {
for (let i = 0; i < circles.length; i++) {
  for (let j = i + 1; j < circles.length; j++) {
    const circle1 = circles[i];
    const circle2 = circles[j];

    // Calculate distance between two circles
    const dx = circle1.x - circle2.x;
    const dy = circle1.y - circle2.y;
    const distance = Math.sqrt(dx * dx + dy * dy);

    // Draw line if distance is less than connection distance
    if (distance < config.connectionDistance) {
      // Opacity based on distance (closer = more opaque)
      const opacity = 1 - (distance / config.connectionDistance);
      ctx.beginPath();
      ctx.moveTo(circle1.x, circle1.y);
      ctx.lineTo(circle2.x, circle2.y);
      ctx.strokeStyle = `rgba(52, 152, 219, ${opacity})`;
      ctx.lineWidth = 1;
      ctx.stroke();
      ctx.closePath();
    }
  }
}
}

// Animation loop
function animate() {
requestAnimationFrame(animate);

// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Update and draw circles
circles.forEach(circle => {
  circle.update();
  circle.draw();
});

// Draw connections
drawConnections();
}

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

// Start animation
init();
animate();
});