animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Only CSS: Codevember #6 Money Storm

model output

Claude Sonnet 4.6

Only CSS: Codevember #6 Money Storm

A 0.77T 0.31
compare with ground truth →
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>Money Rain Animation</title>
7<style>
8  * { margin: 0; padding: 0; box-sizing: border-box; }
9  
10  body {
11    background: #000;
12    width: 100vw;
13    height: 100vh;
14    overflow: hidden;
15  }
16  
17  canvas {
18    display: block;
19  }
20</style>
21</head>
22<body>
23<canvas id="c"></canvas>
24<script>
25const canvas = document.getElementById('c');
26const ctx = canvas.getContext('2d');
27canvas.width = window.innerWidth;
28canvas.height = window.innerHeight;
29
30const W = canvas.width;
31const H = canvas.height;
32
33// Draw a bill on an offscreen canvas
34function createBillCanvas(w, h) {
35  const bc = document.createElement('canvas');
36  bc.width = w;
37  bc.height = h;
38  const bx = bc.getContext('2d');
39  
40  // Bill background
41  bx.fillStyle = '#e8e8d8';
42  bx.fillRect(0, 0, w, h);
43  
44  // Shadow/fold effect
45  bx.fillStyle = '#d0d0c0';
46  bx.fillRect(0, h * 0.45, w, h * 0.1);
47  
48  // Border
49  bx.strokeStyle = '#c0c0a0';
50  bx.lineWidth = 1;
51  bx.strokeRect(2, 2, w-4, h-4);
52  
53  // Text
54  bx.fillStyle = '#1a4a1a';
55  bx.font = `bold ${Math.floor(h * 0.35)}px Arial`;
56  bx.textAlign = 'center';
57  bx.textBaseline = 'middle';
58  bx.fillText('¥10,000', w/2, h/2);
59  
60  // Small text
61  bx.font = `${Math.floor(h * 0.15)}px Arial`;
62  bx.fillText('¥ 10,000', w/2, h * 0.8);
63  
64  return bc;
65}
66
67const billW = 120;
68const billH = 60;
69const billCanvas = createBillCanvas(billW, billH);
70
71class Bill {
72  constructor(delay) {
73    this.delay = delay;
74    this.reset(true);
75  }
76  
77  reset(initial) {
78    // Start from upper-right area (matching the video)
79    this.x = W * 0.4 + Math.random() * W * 0.4;
80    this.y = initial ? -Math.random() * H * 0.5 - 50 : -80;
81    
82    // Velocity - bills fall and spread
83    this.vx = (Math.random() - 0.7) * 3;
84    this.vy = 1.5 + Math.random() * 2.5;
85    
86    // Rotation
87    this.angle = Math.random() * Math.PI * 2;
88    this.rotX = (Math.random() - 0.5) * 0.08; // 3D-like rotation speed X
89    this.rotZ = (Math.random() - 0.5) * 0.05; // Z rotation speed
90    
91    // Scale for perspective effect
92    this.scale = 0.3 + Math.random() * 1.2;
93    this.scaleX = 1; // for 3D flip effect
94    this.scaleXDir = (Math.random() > 0.5 ? 1 : -1) * 0.02;
95    
96    // Wobble
97    this.wobble = Math.random() * Math.PI * 2;
98    this.wobbleSpeed = 0.05 + Math.random() * 0.05;
99    
100    this.alive = true;
101    this.born = false;
102    this.birthTime = this.delay;
103  }
104  
105  update(t) {
106    if (t < this.birthTime) return;
107    this.born = true;
108    
109    this.x += this.vx;
110    this.y += this.vy;
111    this.vy += 0.02; // gravity
112    this.vx += (Math.random() - 0.5) * 0.1;
113    
114    this.angle += this.rotZ;
115    this.wobble += this.wobbleSpeed;
116    
117    // 3D flip effect
118    this.scaleX += this.scaleXDir;
119    if (Math.abs(this.scaleX) > 1) this.scaleXDir *= -1;
120    
121    if (this.y > H + 100) {
122      this.alive = false;
123    }
124  }
125  
126  draw(ctx) {
127    if (!this.born) return;
128    
129    ctx.save();
130    ctx.translate(this.x, this.y);
131    ctx.rotate(this.angle);
132    ctx.scale(this.scale * this.scaleX, this.scale * (0.7 + 0.3 * Math.abs(Math.sin(this.wobble))));
133    
134    // Draw bill with fold effect
135    ctx.drawImage(billCanvas, -billW/2, -billH/2, billW, billH);
136    
137    // Add shadow/3D fold
138    if (this.scaleX > 0.3) {
139      ctx.fillStyle = 'rgba(0,0,0,0.2)';
140      ctx.fillRect(-billW/2, -billH/2 + billH * 0.4, billW, billH * 0.15);
141    }
142    
143    ctx.restore();
144  }
145}
146
147// Create bills with staggered delays
148const bills = [];
149const totalBills = 35;
150
151for (let i = 0; i < totalBills; i++) {
152  bills.push(new Bill(i * 80)); // stagger by 80ms
153}
154
155let startTime = null;
156let lastSpawn = 0;
157
158function animate(timestamp) {
159  if (!startTime) startTime = timestamp;
160  const elapsed = timestamp - startTime;
161  
162  ctx.clearRect(0, 0, W, H);
163  ctx.fillStyle = '#000';
164  ctx.fillRect(0, 0, W, H);
165  
166  // Respawn dead bills
167  for (let b of bills) {
168    b.update(elapsed);
169    if (!b.alive) {
170      b.delay = elapsed + Math.random() * 500;
171      b.x = W * 0.3 + Math.random() * W * 0.5;
172      b.y = -80;
173      b.vx = (Math.random() - 0.6) * 3;
174      b.vy = 1.5 + Math.random() * 2;
175      b.angle = Math.random() * Math.PI * 2;
176      b.scale = 0.3 + Math.random() * 1.2;
177      b.scaleX = 1;
178      b.scaleXDir = (Math.random() > 0.5 ? 1 : -1) * 0.02;
179      b.wobble = Math.random() * Math.PI * 2;
180      b.alive = true;
181      b.born = false;
182      b.birthTime = b.delay;
183    }
184    b.draw(ctx);
185  }
186  
187  requestAnimationFrame(animate);
188}
189
190requestAnimationFrame(animate);
191
192window.addEventListener('resize', () => {
193  canvas.width = window.innerWidth;
194  canvas.height = window.innerHeight;
195});
196</script>
197</body>
198</html>