← back to Nice spinny stuffcompare with ground truth →
model output
GPT-5.4
Nice spinny stuff
A 0.89T 0.28
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8" />
5<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6<title>Pink Heart Dots Animation</title>
7<style>
8 html, body {
9 margin: 0;
10 width: 100%;
11 height: 100%;
12 overflow: hidden;
13 background: #fff;
14 }
15
16 body {
17 position: relative;
18 font-family: sans-serif;
19 }
20
21 /* Match the small cluster in the upper-left area */
22 .scene {
23 position: absolute;
24 left: 12.5vw;
25 top: 12vh;
26 width: 120px;
27 height: 120px;
28 }
29
30 .heart {
31 position: absolute;
32 left: 0;
33 top: 0;
34 width: 120px;
35 height: 120px;
36 }
37
38 .dot {
39 position: absolute;
40 left: 0;
41 top: 0;
42 width: 8px;
43 height: 8px;
44 margin: -4px 0 0 -4px;
45 border-radius: 50%;
46 background: #ffc3d3;
47 opacity: .92;
48 transform: translate(var(--x), var(--y)) scale(var(--s, 1));
49 box-shadow: 0 0 0 0.5px rgba(255,195,211,.15);
50 }
51
52 .dot.big {
53 width: 12px;
54 height: 12px;
55 margin: -6px 0 0 -6px;
56 background: #ffbfd0;
57 }
58
59 .dot.small {
60 width: 6px;
61 height: 6px;
62 margin: -3px 0 0 -3px;
63 opacity: .82;
64 }
65
66 .orbit {
67 position: absolute;
68 inset: 0;
69 animation: orbit 1.6s linear infinite;
70 }
71
72 .pulse {
73 animation: pulse 1.6s ease-in-out infinite;
74 transform-origin: 50% 50%;
75 }
76
77 @keyframes orbit {
78 0% { transform: rotate(-18deg); }
79 25% { transform: rotate(72deg); }
80 50% { transform: rotate(162deg); }
81 75% { transform: rotate(252deg); }
82 100% { transform: rotate(342deg); }
83 }
84
85 @keyframes pulse {
86 0%, 100% { transform: scale(0.98); opacity: .92; }
87 50% { transform: scale(1.03); opacity: 1; }
88 }
89</style>
90</head>
91<body>
92 <div class="scene">
93 <div class="heart pulse" id="heart"></div>
94 <div class="orbit" id="orbit"></div>
95 </div>
96
97<script>
98 const heart = document.getElementById('heart');
99 const orbit = document.getElementById('orbit');
100
101 // Heart outline points, sized/placed to match the tiny pastel heart.
102 function heartPoint(t, scale = 1) {
103 const x = 16 * Math.pow(Math.sin(t), 3);
104 const y = -(13 * Math.cos(t) - 5 * Math.cos(2*t) - 2 * Math.cos(3*t) - Math.cos(4*t));
105 return { x: x * scale, y: y * scale };
106 }
107
108 // Static dotted heart outline
109 const cx = 48, cy = 48;
110 const outlineCount = 18;
111 for (let i = 0; i < outlineCount; i++) {
112 const t = (i / outlineCount) * Math.PI * 2;
113 const p = heartPoint(t, 1.15);
114 const d = document.createElement('div');
115 d.className = 'dot' + (i % 3 === 0 ? ' small' : '');
116 d.style.setProperty('--x', `${cx + p.x}px`);
117 d.style.setProperty('--y', `${cy + p.y}px`);
118 heart.appendChild(d);
119 }
120
121 // Inner tiny heart
122 const innerCount = 10;
123 for (let i = 0; i < innerCount; i++) {
124 const t = (i / innerCount) * Math.PI * 2;
125 const p = heartPoint(t, 0.48);
126 const d = document.createElement('div');
127 d.className = 'dot small';
128 d.style.setProperty('--x', `${cx + p.x}px`);
129 d.style.setProperty('--y', `${cy + p.y}px`);
130 d.style.opacity = '.72';
131 heart.appendChild(d);
132 }
133
134 // Three larger dots orbiting around the heart, matching the frame sequence.
135 const orbitDots = [
136 { r: 34, a: 0, s: 1.0 },
137 { r: 28, a: 0.3, s: 0.9 },
138 { r: 22, a: 0.6, s: 0.78 }
139 ];
140
141 orbitDots.forEach((cfg, i) => {
142 const wrap = document.createElement('div');
143 wrap.style.position = 'absolute';
144 wrap.style.left = cx + 'px';
145 wrap.style.top = cy + 'px';
146 wrap.style.width = '0';
147 wrap.style.height = '0';
148 wrap.style.transform = `rotate(${cfg.a}rad)`;
149
150 const d = document.createElement('div');
151 d.className = 'dot big';
152 d.style.setProperty('--x', `${cfg.r}px`);
153 d.style.setProperty('--y', `0px`);
154 d.style.setProperty('--s', cfg.s);
155 d.style.opacity = i === 0 ? '.95' : '.88';
156
157 wrap.appendChild(d);
158 orbit.appendChild(wrap);
159 });
160</script>
161</body>
162</html>