← back to Neon Loaderscompare with ground truth →
model output
Claude Sonnet 4.6
Neon Loaders
A 0.72T 0.27
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>Neon Loading Bar</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 width: 100vw;
12 height: 100vh;
13 background: radial-gradient(ellipse at center, #1a2a28 0%, #0d1a18 40%, #080f0e 100%);
14 display: flex;
15 align-items: center;
16 justify-content: center;
17 overflow: hidden;
18 }
19
20 .container {
21 position: relative;
22 width: 240px;
23 height: 40px;
24 }
25
26 /* Dark background bar */
27 .bar-bg {
28 position: absolute;
29 width: 240px;
30 height: 40px;
31 background: #3a3f45;
32 border-radius: 2px;
33 }
34
35 /* Canvas for the animated lines */
36 canvas {
37 position: absolute;
38 top: 0;
39 left: 0;
40 width: 240px;
41 height: 40px;
42 }
43</style>
44</head>
45<body>
46<div class="container">
47 <div class="bar-bg"></div>
48 <canvas id="c" width="240" height="40"></canvas>
49</div>
50
51<script>
52const canvas = document.getElementById('c');
53const ctx = canvas.getContext('2d');
54const W = 240, H = 40;
55
56// Animation: lines sweep from left to right, color shifts from magenta to cyan/blue
57// Duration ~3 seconds, looping
58
59const DURATION = 3000; // ms for one full cycle
60const start = performance.now();
61
62// Lines configuration: each line has a y position, height, speed offset, color phase offset
63const lines = [
64 { y: 2, h: 2, delay: 0.0 },
65 { y: 5, h: 2, delay: 0.05 },
66 { y: 8, h: 2, delay: 0.08 },
67 { y: 11, h: 2, delay: 0.12 },
68 { y: 14, h: 2, delay: 0.15 },
69 { y: 17, h: 2, delay: 0.18 },
70 { y: 20, h: 2, delay: 0.22 },
71 { y: 23, h: 2, delay: 0.25 },
72 { y: 26, h: 2, delay: 0.28 },
73 { y: 29, h: 2, delay: 0.32 },
74 { y: 32, h: 2, delay: 0.35 },
75 { y: 35, h: 2, delay: 0.38 },
76];
77
78function getColor(t) {
79 // t: 0 to 1
80 // Start: magenta (#ff00ff), transition through purple to blue (#00aaff)
81 const r = Math.round(255 * (1 - t) + 0 * t);
82 const g = Math.round(0 * (1 - t) + 170 * t);
83 const b = Math.round(255);
84 return `rgb(${r},${g},${b})`;
85}
86
87function draw(now) {
88 ctx.clearRect(0, 0, W, H);
89
90 const elapsed = (now - start) % DURATION;
91 const progress = elapsed / DURATION; // 0 to 1
92
93 lines.forEach((line, i) => {
94 // Each line has a slightly different progress based on delay
95 // The line sweeps from left to right
96 // The "head" of the line is at progress position
97 // Lines have varying lengths creating the staggered effect
98
99 const lineProgress = (progress - line.delay + 1) % 1;
100
101 // Line extends from 0 to lineProgress * W (head position)
102 // But with a tail effect - tail lags behind
103 const headX = lineProgress * W;
104 const tailLength = W * 0.3; // tail is 30% of bar width
105 const tailX = Math.max(0, headX - tailLength);
106
107 if (headX <= 0) return;
108
109 // Color based on overall progress
110 const colorT = lineProgress;
111
112 // Create gradient for the line (tail fades out)
113 const grad = ctx.createLinearGradient(tailX, 0, headX, 0);
114 const col = getColor(colorT);
115 grad.addColorStop(0, 'rgba(0,0,0,0)');
116 grad.addColorStop(1, col);
117
118 ctx.fillStyle = grad;
119 ctx.fillRect(tailX, line.y, headX - tailX, line.h);
120
121 // Bright head
122 ctx.fillStyle = col;
123 ctx.shadowColor = col;
124 ctx.shadowBlur = 6;
125 ctx.fillRect(Math.max(0, headX - 3), line.y, 3, line.h);
126 ctx.shadowBlur = 0;
127 });
128
129 requestAnimationFrame(draw);
130}
131
132requestAnimationFrame(draw);
133</script>
134</body>
135</html>