← back to SVG Multi-Dripcompare with ground truth →
model output
Claude Sonnet 4.6
SVG Multi-Drip
A 0.70T 0.16
1Looking at the animation, I can see:
2
31. A row of dots arranged horizontally, colored with a gradient from magenta/pink (left) to red (right)
42. Each dot animates with a "bounce" effect - it drops down from the main line, falls, and returns - creating a wave-like ripple effect traveling across the dots
53. The dots are connected in a chain/caterpillar shape when at rest
64. The animation creates a traveling wave where dots sequentially drop down and bounce back up
7
8<!DOCTYPE html>
9<html>
10<head>
11<style>
12 * { margin: 0; padding: 0; box-sizing: border-box; }
13 body { background: #333; display: flex; align-items: center; justify-content: center; height: 100vh; overflow: hidden; }
14 canvas { display: block; }
15</style>
16</head>
17<body>
18<canvas id="c"></canvas>
19<script>
20const canvas = document.getElementById('c');
21const ctx = canvas.getContext('2d');
22canvas.width = 1024;
23canvas.height = 768;
24
25const N = 16;
26const startX = 140;
27const baseY = 190;
28const spacing = 46;
29const radius = 22;
30const cycleTime = 2000; // ms for wave to travel across all dots
31
32function getColor(i) {
33 const t = i / (N - 1);
34 const r = Math.round(255);
35 const g = Math.round(0 + (1 - t) * 0);
36 const b = Math.round((1 - t) * 255 * 0);
37 // magenta = ff00ff, red = ff0000
38 const rr = 255;
39 const gg = Math.round((1 - t) * 0);
40 const bb = Math.round((1 - t) * 255);
41 return `rgb(${rr},${gg},${bb})`;
42}
43
44function easeInOutSine(t) {
45 return -(Math.cos(Math.PI * t) - 1) / 2;
46}
47
48function getDotY(i, time) {
49 // Wave travels left to right
50 // Each dot has a phase offset
51 const waveSpeed = cycleTime;
52 const dotDelay = waveSpeed / N;
53
54 // Phase for this dot
55 const phase = (time - i * dotDelay) / waveSpeed;
56 const p = ((phase % 1) + 1) % 1;
57
58 // Drop down and come back: sine wave, only positive half
59 const dropAmount = 120;
60 const dropY = Math.sin(p * Math.PI) * dropAmount;
61
62 return baseY + dropY;
63}
64
65function getDotRadius(i, time) {
66 const waveSpeed = cycleTime;
67 const dotDelay = waveSpeed / N;
68 const phase = (time - i * dotDelay) / waveSpeed;
69 const p = ((phase % 1) + 1) % 1;
70
71 // Shrink slightly when at bottom
72 const scale = 1 - 0.3 * Math.sin(p * Math.PI);
73 return radius * scale;
74}
75
76function draw(time) {
77 ctx.clearRect(0, 0, canvas.width, canvas.height);
78
79 // Draw dots from right to left so left ones appear on top
80 for (let i = N - 1; i >= 0; i--) {
81 const x = startX + i * spacing;
82 const y = getDotY(i, time);
83 const r = getDotRadius(i, time);
84
85 ctx.beginPath();
86 ctx.arc(x, y, r, 0, Math.PI * 2);
87 ctx.fillStyle = getColor(i);
88 ctx.fill();
89 }
90
91 requestAnimationFrame(draw);
92}
93
94requestAnimationFrame(draw);
95</script>
96</body>
97</html>
98
99Wait, let me re-analyze and create a more accurate version:
100
101<!DOCTYPE html>
102<html>
103<head>
104<style>
105* { margin: 0; padding: 0; box-sizing: border-box; }
106body { background: #333; display: flex; align-items: center; justify-content: center; height: 100vh; }
107canvas { display: block; }
108</style>
109</head>
110<body>
111<canvas id="c" width="1024" height="768"></canvas>
112<script>
113const canvas = document.getElementById('c');
114const ctx = canvas.getContext('2d');
115const N = 16;
116const startX = 145;
117const baseY = 190;
118const spacing = 46;
119const radius = 22;
120const cycleDuration = 2200;
121
122function getColor(i) {
123 const t = i / (N - 1);
124 return `rgb(255,${Math.round((1-t)*0)},${Math.round((1-t)*255)})`;
125}
126
127function draw(time) {
128 ctx.clearRect(0, 0, canvas.width, canvas.height);
129 for (let i = N - 1; i >= 0; i--) {
130 const x = startX + i * spacing;
131 const offset = (i / N) * cycleDuration;
132 const p = ((time - offset) % cycleDuration + cycleDuration) % cycleDuration / cycleDuration;
133 const dropY = Math.sin(p * Math.PI) * 130;
134 const r = radius * (1 - 0.35 * Math.sin(p * Math.PI));
135 const y = baseY + dropY;
136 ctx.beginPath();
137 ctx.arc(x, y, r, 0, Math.PI * 2);
138 ctx.fillStyle = getColor(i);
139 ctx.fill();
140 }
141 requestAnimationFrame(draw);
142}
143requestAnimationFrame(draw);
144</script>
145</body>
146</html>