← back to Bubble Floatcompare with ground truth →
model output
Claude Sonnet 4.6
Bubble Float
A 0.96T 0.63
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>Floating Bubbles</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 background-color: #1a1f27;
12 width: 100vw;
13 height: 100vh;
14 overflow: hidden;
15 position: relative;
16 }
17
18 .bubble {
19 position: absolute;
20 border-radius: 50%;
21 background-color: #4a7f8a;
22 opacity: 0.75;
23 }
24</style>
25</head>
26<body>
27<canvas id="canvas"></canvas>
28
29<script>
30const canvas = document.getElementById('canvas');
31const ctx = canvas.getContext('2d');
32
33canvas.width = window.innerWidth;
34canvas.height = window.innerHeight;
35
36const W = canvas.width;
37const H = canvas.height;
38
39// Background color
40const BG = '#1a1f27';
41const BUBBLE_COLOR = '#4a7f8a';
42
43// Bubble parameters
44// Each bubble: { x, y, r, vx, vy, delay, born }
45// They start from bottom/edges and float upward
46
47const bubbles = [];
48let startTime = null;
49
50// Pre-define bubbles with staggered start times
51// Based on frames: first bubble appears around frame 8 (center-bottom),
52// then more appear from edges, moving upward
53
54function createBubble(x, y, r, vx, vy, delay) {
55 return { x, y, r, vx, vy, delay, startX: x, startY: y };
56}
57
58// Generate many bubbles with various sizes, positions, velocities
59// They appear to rise from bottom and edges
60const bubbleConfigs = [];
61
62// Seed random bubbles
63const rand = (min, max) => min + Math.random() * (max - min);
64
65// Create ~25 bubbles
66for (let i = 0; i < 28; i++) {
67 const r = rand(5, 55);
68 const x = rand(0, W);
69 const y = H + r + rand(0, 200); // start below screen
70 const vx = rand(-0.3, 0.3);
71 const vy = -rand(0.5, 2.5); // upward
72 const delay = rand(0, 8000); // stagger over 8 seconds
73 bubbleConfigs.push({ x, y, r, vx, vy, delay, startX: x, startY: y });
74}
75
76// Also add some from sides
77for (let i = 0; i < 8; i++) {
78 const r = rand(5, 45);
79 const side = Math.random() < 0.5 ? -r : W + r;
80 const x = side;
81 const y = rand(H * 0.3, H);
82 const vx = side < 0 ? rand(0.3, 1.5) : -rand(0.3, 1.5);
83 const vy = -rand(0.3, 1.5);
84 const delay = rand(0, 8000);
85 bubbleConfigs.push({ x, y, r, vx, vy, delay, startX: x, startY: y });
86}
87
88function draw(timestamp) {
89 if (!startTime) startTime = timestamp;
90 const elapsed = timestamp - startTime;
91
92 ctx.fillStyle = BG;
93 ctx.fillRect(0, 0, W, H);
94
95 ctx.globalCompositeOperation = 'source-over';
96
97 for (const b of bubbleConfigs) {
98 if (elapsed < b.delay) continue;
99
100 const t = (elapsed - b.delay) / 1000; // seconds since this bubble started
101
102 const x = b.startX + b.vx * t * 60;
103 const y = b.startY + b.vy * t * 60;
104
105 // Skip if way off screen
106 if (y < -b.r * 2 || x < -b.r * 2 || x > W + b.r * 2) continue;
107
108 ctx.beginPath();
109 ctx.arc(x, y, b.r, 0, Math.PI * 2);
110 ctx.fillStyle = BUBBLE_COLOR;
111 ctx.globalAlpha = 0.72;
112 ctx.fill();
113 ctx.globalAlpha = 1;
114 }
115
116 requestAnimationFrame(draw);
117}
118
119requestAnimationFrame(draw);
120
121window.addEventListener('resize', () => {
122 canvas.width = window.innerWidth;
123 canvas.height = window.innerHeight;
124});
125</script>
126</body>
127</html>