library / retro & cyberpunk / cyber-fiber-optics
live - 60fps 1920 x 1080
cyber-fiber-optics.html - self-contained
<!DOCTYPE html>
<html>
<head>
<title>Cyber Fiber Optics</title>
<style>
  body, html {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: radial-gradient(ellipse at center, #0a1128 0%, #000000 70%);
  }
  .optic-canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
</style>
</head>
<body>
<canvas class="optic-canvas"></canvas>
<script>
  const canvas = document.querySelector('.optic-canvas');
  const ctx = canvas.getContext('2d');
  let width, height, centerX, centerY;
  let particles = [];

  function setSize() {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
    centerX = width / 2;
    centerY = height / 2;
  }

  class Particle {
    constructor() {
      this.reset();
    }
    reset() {
        this.z = Math.random() * width;
        const angle = Math.random() * Math.PI * 2;
        const radius = Math.random() * (width / 3);
        this.x = centerX + Math.cos(angle) * radius;
        this.y = centerY + Math.sin(angle) * radius;
        this.speed = 1 + Math.random() * 3;
        this.hue = 180 + Math.random() * 50;
    }
    update() {
      this.z -= this.speed;
      if (this.z < 1) {
        this.reset();
      }
    }
    draw() {
        const scale = width / this.z;
        const x2d = (this.x - centerX) * scale + centerX;
        const y2d = (this.y - centerY) * scale + centerY;
        
        const prev_scale = width / (this.z + this.speed * 10);
        const prev_x2d = (this.x - centerX) * prev_scale + centerX;
        const prev_y2d = (this.y - centerY) * prev_scale + centerY;

        ctx.beginPath();
        ctx.moveTo(prev_x2d, prev_y2d);
        ctx.lineTo(x2d, y2d);
        ctx.lineWidth = scale * 1.5;
        ctx.strokeStyle = `hsla(${this.hue}, 80%, 60%, ${0.1 + 0.8 * (1 - this.z/width)})`;
        ctx.stroke();
    }
  }

  function init() {
    setSize();
    particles = [];
    for (let i = 0; i < 600; i++) {
      particles.push(new Particle());
    }
  }

  function animate() {
    ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
    ctx.fillRect(0, 0, width, height);

    particles.forEach(p => {
      p.update();
      p.draw();
    });
    requestAnimationFrame(animate);
  }

  window.addEventListener('resize', setSize);
  init();
  animate();
</script>
</body>
</html>

About this animation

Glowing fiber optic strands carrying data.

Under the hood

Canvas Bezier Flow

This draws hundreds of cubic Bezier curves across the canvas, assigning highly saturated, glowing strokeStyle colors with globalCompositeOperation = 'lighter' to create stunning overlapping light blooms.

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