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

model output

Claude Sonnet 4.6

Nice spinny stuff

A 0.92T 0.23
compare with ground truth →
1Looking at the animation, I can see a heart shape made of pink dots that appears to be "drawing" itself - dots appear one by one tracing the outline of a heart shape, with the leading dot being slightly larger/darker. The heart is positioned in the upper-left area of the screen, and the animation loops continuously.
2
3<!DOCTYPE html>
4<html lang="en">
5<head>
6<meta charset="UTF-8">
7<meta name="viewport" content="width=device-width, initial-scale=1.0">
8<title>Heart Dot Animation</title>
9<style>
10  * { margin: 0; padding: 0; box-sizing: border-box; }
11  body { background: white; width: 1024px; height: 768px; overflow: hidden; }
12  canvas { display: block; }
13</style>
14</head>
15<body>
16<canvas id="c" width="1024" height="768"></canvas>
17<script>
18const canvas = document.getElementById('c');
19const ctx = canvas.getContext('2d');
20
21// Heart center position (upper-left area based on frames)
22const cx = 160;
23const cy = 160;
24const heartSize = 28;
25
26// Generate heart path points
27function heartPoint(t) {
28  // Parametric heart curve
29  const x = heartSize * 16 * Math.pow(Math.sin(t), 3) / 16;
30  const y = -heartSize * (13 * Math.cos(t) - 5 * Math.cos(2*t) - 2 * Math.cos(3*t) - Math.cos(4*t)) / 16;
31  return { x: cx + x, y: cy + y };
32}
33
34const numDots = 24;
35const dots = [];
36for (let i = 0; i < numDots; i++) {
37  const t = (i / numDots) * Math.PI * 2;
38  const p = heartPoint(t);
39  dots.push(p);
40}
41
42const totalDuration = 2000; // ms for one full loop
43let startTime = null;
44
45function draw(timestamp) {
46  if (!startTime) startTime = timestamp;
47  const elapsed = (timestamp - startTime) % totalDuration;
48  const progress = elapsed / totalDuration; // 0 to 1
49
50  ctx.clearRect(0, 0, canvas.width, canvas.height);
51
52  // How many dots are visible: cycles through 0 to numDots continuously
53  const visibleCount = Math.floor(progress * numDots) + 1;
54  const leadProgress = (progress * numDots) % 1; // fractional position of lead dot
55
56  for (let i = 0; i < numDots; i++) {
57    const dotIndex = i;
58    
59    // Determine if this dot should be visible
60    // The "tail" - dots that have been drawn
61    // Leading dot index
62    const leadIndex = (Math.floor(progress * numDots)) % numDots;
63    
64    // Calculate how far behind the lead this dot is
65    let behind = (leadIndex - dotIndex + numDots) % numDots;
66    
67    if (behind >= numDots) continue;
68    
69    const dot = dots[dotIndex];
70    
71    // Fade based on how far behind the lead
72    let alpha, radius;
73    
74    if (behind === 0) {
75      // Lead dot - largest and most opaque
76      alpha = 0.9;
77      radius = 5.5;
78    } else {
79      // Trail dots - fade out
80      const fadeRatio = 1 - (behind / numDots);
81      alpha = 0.15 + fadeRatio * 0.55;
82      radius = 2.5 + fadeRatio * 2;
83    }
84    
85    ctx.beginPath();
86    ctx.arc(dot.x, dot.y, radius, 0, Math.PI * 2);
87    ctx.fillStyle = `rgba(255, 182, 193, ${alpha})`;
88    ctx.fill();
89  }
90
91  requestAnimationFrame(draw);
92}
93
94requestAnimationFrame(draw);
95</script>
96</body>
97</html>