← back to Nice spinny stuffcompare with ground truth →
model output
Claude Sonnet 4.6
Nice spinny stuff
A 0.92T 0.23
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>