1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width, initial-scale=1.0">
6<title>Fiber Optic Burst</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 background: #050d18;
12 width: 100vw;
13 height: 100vh;
14 overflow: hidden;
15 display: flex;
16 align-items: center;
17 justify-content: center;
18 }
19
20 canvas {
21 display: block;
22 }
23</style>
24</head>
25<body>
26<canvas id="c"></canvas>
27<script>
28const canvas = document.getElementById('c');
29const ctx = canvas.getContext('2d');
30
31canvas.width = window.innerWidth;
32canvas.height = window.innerHeight;
33
34const cx = canvas.width / 2;
35const cy = canvas.height / 2;
36
37const NUM_RAYS = 28;
38const rays = [];
39
40function randomBetween(a, b) {
41 return a + Math.random() * (b - a);
42}
43
44// Colors: white/silver and cyan/teal/blue
45const colorSets = [
46 { tip: '#ffffff', base: '#aaccdd' },
47 { tip: '#ffffff', base: '#88aacc' },
48 { tip: '#00eeff', base: '#0088cc' },
49 { tip: '#00ffcc', base: '#008866' },
50 { tip: '#44ccff', base: '#0055aa' },
51 { tip: '#00ddff', base: '#005588' },
52 { tip: '#ffffff', base: '#99bbcc' },
53 { tip: '#00ffee', base: '#009977' },
54];
55
56function createRay(index) {
57 const angle = (index / NUM_RAYS) * Math.PI * 2 + randomBetween(-0.1, 0.1);
58 const colorSet = colorSets[Math.floor(Math.random() * colorSets.length)];
59 const maxLen = randomBetween(180, 420);
60 const width = randomBetween(3, 6);
61 const speed = randomBetween(0.4, 1.2);
62 const phase = randomBetween(0, Math.PI * 2);
63
64 return {
65 angle,
66 colorSet,
67 maxLen,
68 width,
69 speed,
70 phase,
71 currentLen: randomBetween(50, maxLen),
72 growing: Math.random() > 0.5,
73 rotOffset: randomBetween(-0.02, 0.02),
74 };
75}
76
77for (let i = 0; i < NUM_RAYS; i++) {
78 rays.push(createRay(i));
79}
80
81let globalRotation = 0;
82let time = 0;
83
84// Center glow pulse
85function drawCenter() {
86 const pulse = 0.7 + 0.3 * Math.sin(time * 0.05);
87
88 // Outer glow
89 let grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, 60 * pulse);
90 grad.addColorStop(0, 'rgba(100, 220, 255, 0.6)');
91 grad.addColorStop(0.3, 'rgba(50, 150, 255, 0.3)');
92 grad.addColorStop(1, 'rgba(0, 50, 100, 0)');
93 ctx.fillStyle = grad;
94 ctx.beginPath();
95 ctx.arc(cx, cy, 60 * pulse, 0, Math.PI * 2);
96 ctx.fill();
97
98 // Inner bright core
99 grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, 15 * pulse);
100 grad.addColorStop(0, 'rgba(255, 255, 255, 1)');
101 grad.addColorStop(0.4, 'rgba(100, 220, 255, 0.9)');
102 grad.addColorStop(1, 'rgba(0, 100, 200, 0)');
103 ctx.fillStyle = grad;
104 ctx.beginPath();
105 ctx.arc(cx, cy, 15 * pulse, 0, Math.PI * 2);
106 ctx.fill();
107}
108
109function drawRay(ray) {
110 const angle = ray.angle + globalRotation + ray.rotOffset * time;
111 const len = ray.currentLen;
112
113 const startX = cx + Math.cos(angle) * 8;
114 const startY = cy + Math.sin(angle) * 8;
115 const endX = cx + Math.cos(angle) * len;
116 const endY = cy + Math.sin(angle) * len;
117
118 // Draw the rod/stick
119 const grad = ctx.createLinearGradient(startX, startY, endX, endY);
120 grad.addColorStop(0, ray.colorSet.base + 'ff');
121 grad.addColorStop(0.7, ray.colorSet.tip + 'cc');
122 grad.addColorStop(1, ray.colorSet.tip + 'ff');
123
124 ctx.beginPath();
125 ctx.moveTo(startX, startY);
126 ctx.lineTo(endX, endY);
127 ctx.strokeStyle = grad;
128 ctx.lineWidth = ray.width;
129 ctx.lineCap = 'round';
130 ctx.stroke();
131
132 // Glowing tip
133 const tipGrad = ctx.createRadialGradient(endX, endY, 0, endX, endY, ray.width * 2.5);
134 tipGrad.addColorStop(0, ray.colorSet.tip + 'ff');
135 tipGrad.addColorStop(0.5, ray.colorSet.tip + '88');
136 tipGrad.addColorStop(1, ray.colorSet.tip + '00');
137 ctx.fillStyle = tipGrad;
138 ctx.beginPath();
139 ctx.arc(endX, endY, ray.width * 2.5, 0, Math.PI * 2);
140 ctx.fill();
141
142 // Soft glow along the rod
143 ctx.beginPath();
144 ctx.moveTo(startX, startY);
145 ctx.lineTo(endX, endY);
146 ctx.strokeStyle = ray.colorSet.tip + '22';
147 ctx.lineWidth = ray.width * 4;
148 ctx.lineCap = 'round';
149 ctx.stroke();
150}
151
152function animate() {
153 // Dark background with slight trail
154 ctx.fillStyle = 'rgba(5, 13, 24, 0.25)';
155 ctx.fillRect(0, 0, canvas.width, canvas.height);
156
157 // Slow global rotation
158 globalRotation += 0.003;
159 time++;
160
161 // Update ray lengths - pulsing in and out
162 rays.forEach((ray, i) => {
163 const wave = Math.sin(time * ray.speed * 0.02 + ray.phase);
164 ray.currentLen = ray.maxLen * (0.3 + 0.7 * (0.5 + 0.5 * wave));
165
166 // Occasionally vary the max length
167 if (Math.random() < 0.005) {
168 ray.maxLen = randomBetween(150, 450);
169 }
170 });
171
172 // Draw rays
173 ctx.save();
174 rays.forEach(ray => drawRay(ray));
175 ctx.restore();
176
177 // Draw center glow on top
178 drawCenter();
179
180 requestAnimationFrame(animate);
181}
182
183// Initial clear
184ctx.fillStyle = '#050d18';
185ctx.fillRect(0, 0, canvas.width, canvas.height);
186
187animate();
188
189window.addEventListener('resize', () => {
190 canvas.width = window.innerWidth;
191 canvas.height = window.innerHeight;
192});
193</script>
194</body>
195</html>