animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Only CSS: Sunset Beach

model output

Claude Sonnet 4.6

Only CSS: Sunset Beach

A 0.92T 0.20
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>Red Helmet 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    display: flex;
15    align-items: center;
16    justify-content: center;
17    overflow: hidden;
18  }
19
20  .scene {
21    position: relative;
22    width: 1024px;
23    height: 768px;
24  }
25
26  canvas {
27    position: absolute;
28    top: 0;
29    left: 0;
30  }
31</style>
32</head>
33<body>
34<div class="scene">
35  <canvas id="c" width="1024" height="768"></canvas>
36</div>
37
38<script>
39const canvas = document.getElementById('c');
40const ctx = canvas.getContext('2d');
41
42function drawHelmet(t) {
43  ctx.clearRect(0, 0, 1024, 768);
44  ctx.fillStyle = '#000';
45  ctx.fillRect(0, 0, 1024, 768);
46
47  // Subtle breathing/pulsing animation
48  const pulse = Math.sin(t * 0.5) * 2;
49  
50  const cx = 512;
51  const cy = 370;
52
53  ctx.fillStyle = '#ff0000';
54  ctx.beginPath();
55
56  // Main helmet dome - semicircle top
57  // Center around (512, 370)
58  // Dome radius ~110px
59  const r = 110 + pulse * 0.3;
60  const domeY = cy - 20;
61
62  // Draw the helmet shape using path
63  ctx.beginPath();
64  
65  // Top dome arc
66  ctx.arc(cx, domeY, r, Math.PI, 0, false);
67  
68  // Right side going down to brim
69  ctx.lineTo(cx + r + 30, domeY + 30);
70  // Right brim bump
71  ctx.quadraticCurveTo(cx + r + 45, domeY + 45, cx + r + 20, domeY + 55);
72  ctx.quadraticCurveTo(cx + r + 5, domeY + 60, cx + r - 10, domeY + 50);
73  
74  // Bottom of brim going left
75  ctx.lineTo(cx - r + 10, domeY + 50);
76  
77  // Left brim
78  ctx.quadraticCurveTo(cx - r - 10, domeY + 55, cx - r - 20, domeY + 45);
79  ctx.quadraticCurveTo(cx - r - 35, domeY + 30, cx - r - 10, domeY + 20);
80  ctx.lineTo(cx - r, domeY);
81  
82  ctx.closePath();
83  ctx.fill();
84
85  // Chin strap / neck area - connecting piece
86  ctx.beginPath();
87  ctx.moveTo(cx - 10, domeY + 55);
88  ctx.lineTo(cx + 30, domeY + 55);
89  ctx.quadraticCurveTo(cx + 40, domeY + 65, cx + 35, domeY + 75);
90  ctx.lineTo(cx + 20, domeY + 80);
91  ctx.quadraticCurveTo(cx + 10, domeY + 85, cx, domeY + 82);
92  ctx.quadraticCurveTo(cx - 15, domeY + 80, cx - 20, domeY + 70);
93  ctx.quadraticCurveTo(cx - 15, domeY + 60, cx - 10, domeY + 55);
94  ctx.closePath();
95  ctx.fill();
96
97  // Small drip/puddle below
98  ctx.beginPath();
99  ctx.ellipse(cx + 10, domeY + 105, 35, 18, 0.1, 0, Math.PI * 2);
100  ctx.fill();
101}
102
103let startTime = null;
104
105function animate(timestamp) {
106  if (!startTime) startTime = timestamp;
107  const t = (timestamp - startTime) / 1000;
108  
109  drawHelmet(t);
110  requestAnimationFrame(animate);
111}
112
113requestAnimationFrame(animate);
114</script>
115</body>
116</html>