animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to sting

model output

Claude Sonnet 4.6

sting

A 0.75T 0.30
compare with ground truth →
1Looking at the animation, I can see:
2- A pinwheel/star shape with 6 arms, each made of 3 elongated oval segments
3- The shape alternates between "open" (arms spread out like a starfish) and "closed" (compact pinwheel)
4- Colors gradient from pink/magenta on the left to blue/indigo on the right, with purple in between
5- The whole shape slowly rotates
6- There are faint spiral trail lines visible during transitions
7- The animation cycles with easing (ease-in-out)
8
9Each arm has 3 segments: a large inner oval, medium middle oval, and small outer oval, with the outer ones at an angle (like a bent arm).
10
11<!DOCTYPE html>
12<html>
13<head>
14<style>
15* { margin: 0; padding: 0; box-sizing: border-box; }
16body {
17  width: 100vw; height: 100vh;
18  background: radial-gradient(ellipse at 70% 40%, #d8d8e8 0%, #e8e8f0 40%, #f0f0f5 100%);
19  display: flex; align-items: center; justify-content: center;
20  overflow: hidden;
21}
22canvas { display: block; }
23</style>
24</head>
25<body>
26<canvas id="c"></canvas>
27<script>
28const canvas = document.getElementById('c');
29const ctx = canvas.getContext('2d');
30canvas.width = window.innerWidth;
31canvas.height = window.innerHeight;
32
33const cx = canvas.width / 2 - 20;
34const cy = canvas.height / 2 + 10;
35
36// 6 arms, each with 3 segments
37// Colors: arm 0=pink, arm 1=magenta, arm 2=purple-pink, arm 3=purple, arm 4=blue-purple, arm 5=blue
38const armColors = [
39  '#e040a0', // hot pink
40  '#cc3399', // magenta
41  '#9933cc', // purple-pink
42  '#7744cc', // purple
43  '#5544dd', // blue-purple
44  '#4444cc', // blue-indigo
45];
46
47// Each arm: base angle, 3 segments
48// In "open" state: segments are spread out (like starfish arms)
49// In "closed" state: segments form compact pinwheel petals
50
51function lerp(a, b, t) { return a + (b - a) * t; }
52
53function easeInOut(t) {
54  return t < 0.5 ? 2*t*t : -1+(4-2*t)*t;
55}
56
57// Draw an elongated oval (ellipse) at position, with given angle and size
58function drawSegment(x, y, angle, w, h, color, alpha) {
59  ctx.save();
60  ctx.globalAlpha = alpha;
61  ctx.translate(x, y);
62  ctx.rotate(angle);
63  ctx.beginPath();
64  ctx.ellipse(0, 0, w, h, 0, 0, Math.PI * 2);
65  ctx.fillStyle = color;
66  ctx.shadowColor = 'rgba(0,0,0,0.15)';
67  ctx.shadowBlur = 6;
68  ctx.fill();
69  ctx.restore();
70}
71
72// Arm definition: 3 segments per arm
73// Segment: {dist from center, angle offset from arm direction, own rotation, w, h}
74// "open" = arms extended outward with bent tips
75// "closed" = compact pinwheel
76
77const NUM_ARMS = 6;
78const BASE_ANGLES_OPEN = Array.from({length: NUM_ARMS}, (_, i) => i * Math.PI * 2 / NUM_ARMS);
79
80// Segment sizes
81const SEG = [
82  {w: 14, h: 48}, // inner large
83  {w: 10, h: 32}, // middle
84  {w: 6, h: 20},  // outer small
85];
86
87// Open state: segments along arm direction, spread out
88function getOpenSegments(armAngle) {
89  // inner segment: close to center, along arm
90  // middle: further out
91  // outer: even further, slightly bent
92  return [
93    { dist: 55, angleOff: 0, rotOff: 0, ...SEG[0] },
94    { dist: 110, angleOff: 0, rotOff: 0, ...SEG[1] },
95    { dist: 155, angleOff: 0.3, rotOff: 0.3, ...SEG[2] },
96  ];
97}
98
99// Closed state: compact pinwheel - segments rotated ~45deg from arm, closer
100function getClosedSegments(armAngle) {
101  return [
102    { dist: 45, angleOff: -0.5, rotOff: -0.5, ...SEG[0] },
103    { dist: 85, angleOff: -0.3, rotOff: -0.3, ...SEG[1] },
104    { dist: 118, angleOff: 0.2, rotOff: 0.2, ...SEG[2] },
105  ];
106}
107
108let startTime = null;
109const CYCLE = 3000; // ms per cycle
110const OPEN_HOLD = 0.3;
111const CLOSE_HOLD = 0.3;
112const TRANS = 0.2;
113
114// Global rotation speed
115const ROT_SPEED = 0.0003; // rad/ms
116
117function getPhaseAndT(elapsed) {
118  const t = (elapsed % CYCLE) / CYCLE;
119  // 0 -> OPEN_HOLD: open hold
120  // OPEN_HOLD -> OPEN_HOLD+TRANS: open->close
121  // OPEN_HOLD+TRANS -> OPEN_HOLD+TRANS+CLOSE_HOLD: close hold
122  // rest: close->open
123  const p1 = OPEN_HOLD;
124  const p2 = p1 + TRANS;
125  const p3 = p2 + CLOSE_HOLD;
126  const p4 = p3 + TRANS;
127  
128  if (t < p1) return { phase: 'open', blend: 0 };
129  if (t < p2) return { phase: 'closing', blend: easeInOut((t - p1) / TRANS) };
130  if (t < p3) return { phase: 'closed', blend: 1 };
131  if (t < p4) return { phase: 'opening', blend: easeInOut(1 - (t - p3) / TRANS) };
132  return { phase: 'open', blend: 0 };
133}
134
135function drawArm(armIdx, globalAngle, blend) {
136  const baseAngle = BASE_ANGLES_OPEN[armIdx] + globalAngle;
137  const color = armColors[armIdx];
138  
139  const openSegs = getOpenSegments(baseAngle);
140  const closedSegs = getClosedSegments(baseAngle);
141  
142  for (let s = 0; s < 3; s++) {
143    const os = openSegs[s];
144    const cs = closedSegs[s];
145    
146    const dist = lerp(os.dist, cs.dist, blend);
147    const angleOff = lerp(os.angleOff, cs.angleOff, blend);
148    const rotOff = lerp(os.rotOff, cs.rotOff, blend);
149    const w = lerp(os.w, cs.w, blend);
150    const h = lerp(os.h, cs.h, blend);
151    
152    const posAngle = baseAngle + angleOff;
153    const x = cx + Math.cos(posAngle) * dist;
154    const y = cy + Math.sin(posAngle) * dist;
155    const rot = baseAngle + rotOff + Math.PI / 2;
156    
157    // Alpha: outer segments fade slightly
158    const alpha = s === 2 ? 0.85 : 1.0;
159    drawSegment(x, y, rot, w, h, color, alpha);
160  }
161}
162
163// Draw faint spiral trails during transitions
164function drawTrails(blend, globalAngle) {
165  if (blend < 0.05 || blend > 0.95) return;
166  const trailAlpha = Math.sin(blend * Math.PI) * 0.12;
167  ctx.save();
168  ctx.globalAlpha = trailAlpha;
169  ctx.strokeStyle = '#8866cc';
170  ctx.lineWidth = 1;
171  
172  for (let i = 0; i < 2; i++) {
173    ctx.beginPath();
174    const startA = globalAngle + i * Math.PI;
175    for (let a = 0; a < Math.PI * 2; a += 0.05) {
176      const r = 80 + a * 25;
177      const x = cx + Math.cos(startA + a) * r;
178      const y = cy + Math.sin(startA + a) * r;
179      if (a === 0) ctx.moveTo(x, y);
180      else ctx.lineTo(x, y);
181    }
182    ctx.stroke();
183  }
184  ctx.restore();
185}
186
187function draw(ts) {
188  if (!startTime) startTime = ts;
189  const elapsed = ts - startTime;
190  
191  ctx.clearRect(0, 0, canvas.width, canvas.height);
192  
193  // Background
194  const grad = ctx.createRadialGradient(canvas.width*0.7, canvas.height*0.35, 0, canvas.width*0.5, canvas.height*0.5, canvas.width*0.7);
195  grad.addColorStop(0, '#d5d5e5');
196  grad.addColorStop(0.4, '#e5e5ee');
197  grad.addColorStop(1, '#eeeeF4');
198  ctx.fillStyle = grad;
199  ctx.fillRect(0, 0, canvas.width, canvas.height);
200  
201  const globalAngle = elapsed * ROT_SPEED;
202  const { blend } = getPhaseAndT(elapsed);
203  
204  drawTrails(blend, globalAngle);
205  
206  for (let i = 0; i < NUM_ARMS; i++) {
207    drawArm(i, globalAngle, blend);
208  }
209  
210  requestAnimationFrame(draw);
211}
212
213requestAnimationFrame(draw);
214</script>
215</body>
216</html>