← back to Animated Radio Wavescompare with ground truth →
model output
Claude Sonnet 4.6
Animated Radio Waves
A 0.75T 0.38
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>Wave Animation</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 background: white;
12 width: 1024px;
13 height: 768px;
14 overflow: hidden;
15 position: relative;
16 }
17
18 .scene {
19 position: absolute;
20 top: 0; left: 0;
21 width: 100%; height: 100%;
22 }
23
24 .dot {
25 position: absolute;
26 width: 34px;
27 height: 34px;
28 background: black;
29 border-radius: 50%;
30 top: 143px;
31 left: 957px;
32 transform: translate(-50%, -50%);
33 }
34
35 canvas {
36 position: absolute;
37 top: 0; left: 0;
38 width: 100%; height: 100%;
39 }
40</style>
41</head>
42<body>
43<div class="scene">
44 <canvas id="c"></canvas>
45 <div class="dot"></div>
46</div>
47
48<script>
49 const canvas = document.getElementById('c');
50 canvas.width = 1024;
51 canvas.height = 768;
52 const ctx = canvas.getContext('2d');
53
54 // Origin point (center of dot)
55 const originX = 957;
56 const originY = 143;
57
58 // Each arc: spawns at origin, travels left, fades out
59 const arcs = [];
60 const SPAWN_INTERVAL = 300; // ms between spawns
61 const ARC_DURATION = 2000; // ms for arc to travel and fade
62 const MAX_TRAVEL = 900; // how far left the arc travels
63
64 let lastSpawn = 0;
65
66 function spawnArc(time) {
67 arcs.push({ startTime: time });
68 }
69
70 function drawArc(x, y, size, opacity, darkness) {
71 // Draw a parenthesis-like arc (open to the right)
72 ctx.save();
73 ctx.strokeStyle = `rgba(${darkness},${darkness},${darkness},${opacity})`;
74 ctx.lineWidth = 3.5;
75 ctx.lineCap = 'round';
76 ctx.beginPath();
77 // Arc centered at (x, y), opening to the right
78 // radius ~30, spanning from about -60deg to +60deg on left side
79 const r = size;
80 ctx.arc(x + r * 0.3, y, r, Math.PI * 0.6, Math.PI * 1.4, false);
81 ctx.stroke();
82 ctx.restore();
83 }
84
85 function animate(time) {
86 ctx.clearRect(0, 0, canvas.width, canvas.height);
87
88 // Spawn new arcs
89 if (time - lastSpawn > SPAWN_INTERVAL) {
90 spawnArc(time);
91 lastSpawn = time;
92 }
93
94 // Draw and update arcs
95 for (let i = arcs.length - 1; i >= 0; i--) {
96 const arc = arcs[i];
97 const elapsed = time - arc.startTime;
98 const progress = elapsed / ARC_DURATION;
99
100 if (progress > 1) {
101 arcs.splice(i, 1);
102 continue;
103 }
104
105 // Position: starts near origin, moves left
106 const x = originX - progress * MAX_TRAVEL;
107 const y = originY;
108
109 // Size grows slightly as it moves
110 const size = 20 + progress * 15;
111
112 // Opacity: starts at 1, fades to 0
113 // Near origin it's dark, far away it's light
114 let opacity;
115 if (progress < 0.1) {
116 opacity = progress / 0.1;
117 } else {
118 opacity = 1 - progress;
119 }
120 opacity = Math.max(0, opacity);
121
122 // Darkness: starts dark (0), gets lighter (200) as it moves
123 const darkness = Math.floor(progress * 200);
124
125 drawArc(x, y, size, opacity, darkness);
126 }
127
128 requestAnimationFrame(animate);
129 }
130
131 // Pre-seed some arcs so animation looks populated from start
132 const now = performance.now();
133 for (let i = 0; i < 6; i++) {
134 arcs.push({ startTime: now - i * SPAWN_INTERVAL });
135 }
136 lastSpawn = now;
137
138 requestAnimationFrame(animate);
139</script>
140</body>
141</html>