animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Only CSS: Responsive City Drone View Black

model output

Claude Sonnet 4.6

Only CSS: Responsive City Drone View Black

A 0.49T 0.27
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>Dark Pillars Animation</title>
7<style>
8  * { margin: 0; padding: 0; box-sizing: border-box; }
9  body { background: #000; overflow: hidden; width: 100vw; height: 100vh; }
10  canvas { display: block; }
11</style>
12</head>
13<body>
14<canvas id="c"></canvas>
15<script>
16const canvas = document.getElementById('c');
17const ctx = canvas.getContext('2d');
18canvas.width = window.innerWidth;
19canvas.height = window.innerHeight;
20
21const W = canvas.width;
22const H = canvas.height;
23
24// Vanishing point
25const VP = { x: W * 0.47, y: H * 0.52 };
26
27// Pillar definitions: [x3d, z_start, z_end, width3d, colorTop, colorSide]
28// We'll define pillars in 3D space and project them
29// Each pillar: { x, width, zNear, zFar, colorFace, colorSide }
30
31class Pillar {
32  constructor(x, width, zNear, zFar, brightness) {
33    this.x = x;        // 3D x position
34    this.width = width; // 3D width
35    this.zNear = zNear;
36    this.zFar = zFar;
37    this.brightness = brightness;
38    this.height3d = 400; // tall pillars
39  }
40}
41
42// Define pillars spread around the scene
43const pillarsData = [
44  // x,    w,   zNear, zFar,  brightness
45  [-600,   80,  200,   2000,  0.18],
46  [-300,   60,  200,   2000,  0.15],
47  [-150,   50,  200,   2000,  0.14],
48  [-60,    45,  200,   2000,  0.13],
49  [0,      50,  200,   2000,  0.16],
50  [60,     45,  200,   2000,  0.13],
51  [150,    50,  200,   2000,  0.14],
52  [300,    60,  200,   2000,  0.15],
53  [500,    70,  200,   2000,  0.17],
54  [700,    80,  200,   2000,  0.19],
55  [-800,   90,  200,   2000,  0.20],
56];
57
58// Camera z position - starts far back, moves forward
59let cameraZ = 0;
60const totalDuration = 4000; // ms
61let startTime = null;
62
63function project(x3d, y3d, z3d) {
64  const fov = 600;
65  const dz = z3d - cameraZ;
66  if (dz <= 0) return null;
67  const scale = fov / dz;
68  const sx = VP.x + x3d * scale;
69  const sy = VP.y + y3d * scale;
70  return { x: sx, y: sy, scale };
71}
72
73function drawPillar(p) {
74  const pillarTop = -p.height3d;
75  const pillarBottom = 200; // ground level in 3D
76
77  // Project the 4 vertical edges of the pillar
78  const zNear = p.zNear;
79  const zFar = p.zFar;
80  
81  // Use a single z slice - the pillar extends from zNear to zFar
82  // We'll draw the front face and one side face
83  
84  const x = p.x;
85  const hw = p.width / 2;
86  
87  // Front face corners (at zNear)
88  const tl = project(x - hw, pillarTop, zNear);
89  const tr = project(x + hw, pillarTop, zNear);
90  const bl = project(x - hw, pillarBottom, zNear);
91  const br = project(x + hw, pillarBottom, zNear);
92  
93  // Back face corners (at zFar)
94  const tlb = project(x - hw, pillarTop, zFar);
95  const trb = project(x + hw, pillarTop, zFar);
96  const blb = project(x - hw, pillarBottom, zFar);
97  const brb = project(x + hw, pillarBottom, zFar);
98  
99  if (!tl || !tr || !bl || !br || !tlb || !trb || !blb || !brb) return;
100  
101  const b = p.brightness;
102  const col = `rgb(${Math.round(b*255)},${Math.round(b*255)},${Math.round(b*255)})`;
103  const colDark = `rgb(${Math.round(b*180)},${Math.round(b*180)},${Math.round(b*180)})`;
104  const colTop = `rgb(${Math.round(b*220)},${Math.round(b*220)},${Math.round(b*220)})`;
105  
106  // Draw top face
107  ctx.beginPath();
108  ctx.moveTo(tl.x, tl.y);
109  ctx.lineTo(tr.x, tr.y);
110  ctx.lineTo(trb.x, trb.y);
111  ctx.lineTo(tlb.x, tlb.y);
112  ctx.closePath();
113  ctx.fillStyle = colTop;
114  ctx.fill();
115  
116  // Draw front face (left side of pillar)
117  ctx.beginPath();
118  ctx.moveTo(tl.x, tl.y);
119  ctx.lineTo(tr.x, tr.y);
120  ctx.lineTo(br.x, br.y);
121  ctx.lineTo(bl.x, bl.y);
122  ctx.closePath();
123  ctx.fillStyle = col;
124  ctx.fill();
125  
126  // Draw right side face
127  ctx.beginPath();
128  ctx.moveTo(tr.x, tr.y);
129  ctx.lineTo(trb.x, trb.y);
130  ctx.lineTo(brb.x, brb.y);
131  ctx.lineTo(br.x, br.y);
132  ctx.closePath();
133  ctx.fillStyle = colDark;
134  ctx.fill();
135}
136
137// More detailed pillar setup matching the video
138const pillars = [
139  // Far left large pillar
140  new Pillar(-900, 120, 300, 3000, 0.16),
141  // Left-center pillars
142  new Pillar(-400, 70, 300, 3000, 0.14),
143  new Pillar(-200, 55, 300, 3000, 0.13),
144  // Center pillars (the main ones visible throughout)
145  new Pillar(-80, 50, 300, 3000, 0.15),
146  new Pillar(-20, 45, 300, 3000, 0.14),
147  new Pillar(40, 45, 300, 3000, 0.14),
148  new Pillar(100, 50, 300, 3000, 0.15),
149  // Right-center pillars
150  new Pillar(250, 60, 300, 3000, 0.14),
151  new Pillar(450, 75, 300, 3000, 0.15),
152  // Far right pillars
153  new Pillar(700, 100, 300, 3000, 0.17),
154  new Pillar(950, 120, 300, 3000, 0.18),
155  // Extra far sides
156  new Pillar(-1200, 150, 300, 3000, 0.19),
157];
158
159function animate(timestamp) {
160  if (!startTime) startTime = timestamp;
161  const elapsed = timestamp - startTime;
162  const t = Math.min(elapsed / totalDuration, 1);
163  
164  // Camera moves forward - easeIn
165  // Start at z=0, end at z=1800 (close to pillars)
166  cameraZ = t * t * 1600;
167  
168  ctx.fillStyle = '#000';
169  ctx.fillRect(0, 0, W, H);
170  
171  // Draw ground plane hint
172  // Sort pillars by distance (far to near)
173  const sorted = [...pillars].sort((a, b) => {
174    const da = (a.zNear + a.zFar) / 2 - cameraZ;
175    const db = (b.zNear + b.zFar) / 2 - cameraZ;
176    return db - da;
177  });
178  
179  sorted.forEach(p => drawPillar(p));
180  
181  if (t < 1) {
182    requestAnimationFrame(animate);
183  } else {
184    // Restart
185    startTime = null;
186    requestAnimationFrame(animate);
187  }
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>