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

model output

Claude Sonnet 4.6

Only CSS: Infinite Plug In

A 0.71T 0.62
compare with ground truth →
1<!DOCTYPE html>
2<html>
3<head>
4<style>
5* { margin: 0; padding: 0; box-sizing: border-box; }
6body { background: white; overflow: hidden; width: 100vw; height: 100vh; }
7canvas { display: block; }
8</style>
9</head>
10<body>
11<canvas id="c"></canvas>
12<script>
13const canvas = document.getElementById('c');
14const ctx = canvas.getContext('2d');
15canvas.width = window.innerWidth;
16canvas.height = window.innerHeight;
17
18const W = canvas.width, H = canvas.height;
19
20// Isometric step parameters
21// Steps go from bottom-left to top-right
22// Each step: a flat top parallelogram + a vertical front face
23
24const stepW = 110; // width of step top
25const stepH = 55;  // height of step top (isometric)
26const stepRise = 70; // vertical rise per step
27const stepRun = 110; // horizontal run per step
28
29// Colors for cubes
30const cubeColors = [
31  { top: '#5ec98a', left: '#3aaa6a', right: '#2d8a55' },   // green
32  { top: '#e8834a', left: '#c96020', right: '#a04010' },   // orange
33  { top: '#6b8fd4', left: '#4a6db8', right: '#3050a0' },   // blue
34  { top: '#2a2a8a', left: '#1a1a6a', right: '#0f0f50' },   // dark navy
35  { top: '#9aaa30', left: '#7a8a18', right: '#5a6a08' },   // olive
36];
37
38// Animation: scene scrolls, cubes bounce on steps
39// Steps are arranged diagonally. Let's define step positions.
40
41// The scene moves: everything shifts over time
42// Steps: fixed relative positions, scene offset changes
43
44let t = 0;
45const PERIOD = 5000; // ms per full cycle
46
47// Define steps in scene coords (bottom-left origin of each step)
48// Steps go up-right. Let's place 6 steps.
49// Step i base point (bottom-left corner of top face):
50// x = baseX + i * stepRun, y = baseY - i * stepRise
51
52function getStepPositions(offset) {
53  const steps = [];
54  const baseX = W * 0.05 + offset;
55  const baseY = H * 0.72;
56  for (let i = 0; i < 7; i++) {
57    steps.push({
58      x: baseX + i * stepRun,
59      y: baseY - i * stepRise
60    });
61  }
62  return steps;
63}
64
65// Draw isometric step (folded paper look)
66// Each step has: top parallelogram (light gray), front-left face (darker), front-right face (medium)
67function drawStep(x, y) {
68  // Top face (parallelogram going right and up-right)
69  // Points: bottom-left, bottom-right, top-right, top-left
70  // Isometric: top face
71  const tw = stepW;
72  const th = stepH / 2;
73  
74  // Top face vertices (parallelogram)
75  // bottom-left: (x, y)
76  // bottom-right: (x + tw, y - th)  [going right]
77  // top-right: (x + tw/2, y - th - stepH/2)
78  // top-left: (x - tw/2, y - stepH/2)
79  
80  // Actually let's use a simpler isometric approach
81  // Step top: rhombus
82  // Left face: parallelogram going down
83  // Right face: parallelogram going down-right
84  
85  const hw = tw / 2;
86  const hh = stepH / 2;
87  
88  // Top face
89  ctx.beginPath();
90  ctx.moveTo(x, y);
91  ctx.lineTo(x + hw, y - hh);
92  ctx.lineTo(x + tw, y);
93  ctx.lineTo(x + hw, y + hh);
94  ctx.closePath();
95  const gTop = ctx.createLinearGradient(x, y - hh, x + tw, y + hh);
96  gTop.addColorStop(0, '#f0f0f0');
97  gTop.addColorStop(1, '#d8d8d8');
98  ctx.fillStyle = gTop;
99  ctx.fill();
100  
101  // Left face (going down)
102  const faceH = stepRise * 0.6;
103  ctx.beginPath();
104  ctx.moveTo(x, y);
105  ctx.lineTo(x + hw, y + hh);
106  ctx.lineTo(x + hw, y + hh + faceH);
107  ctx.lineTo(x, y + faceH);
108  ctx.closePath();
109  const gLeft = ctx.createLinearGradient(x, y, x, y + faceH + hh);
110  gLeft.addColorStop(0, '#c0c0c0');
111  gLeft.addColorStop(1, '#888');
112  ctx.fillStyle = gLeft;
113  ctx.fill();
114  
115  // Right face
116  ctx.beginPath();
117  ctx.moveTo(x + hw, y + hh);
118  ctx.lineTo(x + tw, y);
119  ctx.lineTo(x + tw, y + faceH);
120  ctx.lineTo(x + hw, y + hh + faceH);
121  ctx.closePath();
122  const gRight = ctx.createLinearGradient(x + hw, y, x + tw, y + faceH);
123  gRight.addColorStop(0, '#a8a8a8');
124  gRight.addColorStop(1, '#666');
125  ctx.fillStyle = gRight;
126  ctx.fill();
127}
128
129// Draw isometric cube
130function drawCube(cx, cy, size, colors) {
131  const hw = size;
132  const hh = size / 2;
133  
134  // Top face
135  ctx.beginPath();
136  ctx.moveTo(cx, cy - hh);
137  ctx.lineTo(cx + hw, cy);
138  ctx.lineTo(cx, cy + hh);
139  ctx.lineTo(cx - hw, cy);
140  ctx.closePath();
141  ctx.fillStyle = colors.top;
142  ctx.fill();
143  
144  // Left face
145  ctx.beginPath();
146  ctx.moveTo(cx - hw, cy);
147  ctx.lineTo(cx, cy + hh);
148  ctx.lineTo(cx, cy + hh + size);
149  ctx.lineTo(cx - hw, cy + size);
150  ctx.closePath();
151  ctx.fillStyle = colors.left;
152  ctx.fill();
153  
154  // Right face
155  ctx.beginPath();
156  ctx.moveTo(cx, cy + hh);
157  ctx.lineTo(cx + hw, cy);
158  ctx.lineTo(cx + hw, cy + size);
159  ctx.lineTo(cx, cy + hh + size);
160  ctx.closePath();
161  ctx.fillStyle = colors.right;
162  ctx.fill();
163}
164
165// Cube sequence: each cube lands on a step, then bounces up and off
166// The scene scrolls left (or cubes move right relative to steps)
167// Looking at frames: cubes appear from top-right, land on steps, then scene moves
168
169// Let's model it as: scene offset increases over time (scrolling right to left)
170// Cubes are placed at fixed step indices and have a vertical bounce animation
171
172// Cube definitions: step index they land on, color index
173// From frames: green on step 0, orange on step 1, blue on step 2, dark navy on step 3, olive on step 4
174// They cycle through
175
176const NUM_STEPS = 6;
177const CUBE_SIZE = 45;
178
179// Each cube: stepIndex, colorIdx, phase offset
180// The animation cycles: cubes appear above their step, fall down, sit, then scene scrolls
181
182// Simplified: scene scrolls continuously, cubes bounce at their step positions
183// Scroll speed: stepRun per PERIOD * numSteps
184
185const SCROLL_SPEED = (stepRun * 5) / PERIOD; // pixels per ms
186
187// Cube bounce: each cube has a phase. When it's "on screen" it bounces.
188// Cube i is at step i. As scene scrolls, step i moves left.
189// Cube appears when step is at ~3/4 from right, bounces, then exits left.
190
191// Let's track scene offset
192let sceneOffset = 0;
193
194// Cubes: color sequence cycling
195const cubeColorDefs = [
196  { top: '#5ec98a', left: '#3aaa6a', right: '#2d8a55' },   // green
197  { top: '#e8834a', left: '#c96020', right: '#a04010' },   // orange  
198  { top: '#6b8fd4', left: '#4a6db8', right: '#3050a0' },   // blue
199  { top: '#2a2a8a', left: '#1a1a6a', right: '#0f0f50' },   // dark navy
200  { top: '#9aaa30', left: '#7a8a18', right: '#5a6a08' },   // olive
201];
202
203// Steps base: let's define many steps, scene scrolls
204// Step i position: x = baseX - sceneOffset + i*stepRun, y = baseY - i*stepRise
205
206const BASE_X = W * 0.15;
207const BASE_Y = H * 0.78;
208
209// Total steps to render (enough to fill screen)
210const TOTAL_STEPS = 20;
211
212// Cube for step i: color = cubeColorDefs[i % 5]
213// Cube appears above step, bounces down, sits on step
214// Bounce animation tied to when step is at a certain x position
215
216function getCubeY(stepX, stepY, stepIdx) {
217  // Cube sits on top of step
218  // Step top center: (stepX + stepW/2, stepY - stepH/2 + something)
219  // Actually step top face center y = stepY (our y is the left vertex of top face)
220  // Cube bottom = step top surface
221  
222  // The cube "bounces" - it falls from above when the step is near center-right of screen
223  // and then sits on the step
224  
225  const targetX = stepX + stepW / 2;
226  const targetY = stepY - CUBE_SIZE; // sitting on step
227  
228  // Bounce based on step's x position
229  // When step enters from right (x ~ W), cube is high up
230  // When step reaches ~60% from left, cube has landed
231  
232  const progress = 1 - (targetX / W); // 0 when at right, 1 when at left
233  
234  if (progress < 0.1) {
235    // Cube falling from very high
236    const p = Math.max(0, (progress - 0) / 0.1);
237    return targetY - 300 * (1 - p);
238  } else if (progress < 0.5) {
239    // Sitting on step with small bounce
240    const p = (progress - 0.1) / 0.4;
241    const bounce = Math.sin(p * Math.PI * 3) * 20 * (1 - p);
242    return targetY - bounce;
243  } else {
244    return targetY;
245  }
246}
247
248let lastTime = null;
249
250function animate(timestamp) {
251  if (!lastTime) lastTime = timestamp;
252  const dt = timestamp - lastTime;
253  lastTime = timestamp;
254  
255  sceneOffset += SCROLL_SPEED * dt;
256  
257  ctx.clearRect(0, 0, W, H);
258  
259  // Draw steps and cubes from back to front (right to left = higher index first)
260  // Actually draw from right to left for proper overlap
261  
262  const stepsData = [];
263  for (let i = TOTAL_STEPS - 1; i >= 0; i--) {
264    const sx = BASE_X - sceneOffset + i * stepRun;
265    const sy = BASE_Y - i * stepRise;
266    stepsData.push({ i, sx, sy });
267  }
268  
269  // Sort: draw higher steps (larger i, upper-right) first, then lower steps
270  // For isometric, draw back-to-front: larger i first
271  stepsData.sort((a, b) => b.i - a.i);
272  
273  for (const { i, sx, sy } of stepsData) {
274    if (sx + stepW * 2 < 0 || sx - stepW > W) continue;
275    if (sy - stepRise * 2 > H || sy + 200 < 0) continue;
276    
277    drawStep(sx, sy);
278    
279    // Draw cube on this step
280    const colorIdx = ((i % 5) + 5) % 5;
281    const colors = cubeColorDefs[colorIdx];
282    
283    // Cube center x = step center
284    const cubeCX = sx + stepW / 2;
285    const cubeCY = getCubeY(sx, sy, i);
286    
287    // Only draw cube if it's visible and in a reasonable position
288    const stepCenterX = sx + stepW / 2;
289    if (stepCenterX > -100 && stepCenterX < W + 100) {
290      drawCube(cubeCX, cubeCY, CUBE_SIZE, colors);
291    }
292  }
293  
294  requestAnimationFrame(animate);
295}
296
297requestAnimationFrame(animate);
298</script>
299</body>
300</html>