← back to Only CSS: 3D Scancompare with ground truth →
model output
Gemini 3 Flash Preview
Only CSS: 3D Scan
A 0.65T 0.29
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>3D Geometric Sphere Animation</title>
7 <style>
8 :root {
9 --bg-color: #0d121d;
10 --cube-color: rgba(255, 255, 255, 0.05);
11 --ring-cyan: #00f2ff;
12 --ring-blue: #4d4dff;
13 --ring-green: #00ffa2;
14 }
15
16 body, html {
17 margin: 0;
18 padding: 0;
19 width: 100%;
20 height: 100%;
21 background: radial-gradient(circle at center, #1a2639 0%, #080c14 100%);
22 display: flex;
23 justify-content: center;
24 align-items: center;
25 overflow: hidden;
26 perspective: 1200px;
27 }
28
29 .container {
30 position: relative;
31 width: 400px;
32 height: 400px;
33 transform-style: preserve-3d;
34 transform: rotateX(-25deg) rotateY(-35deg);
35 }
36
37 /* Wireframe Cube Structure */
38 .wireframe-cube {
39 position: absolute;
40 top: 50%;
41 left: 50%;
42 width: 300px;
43 height: 300px;
44 margin: -150px;
45 transform-style: preserve-3d;
46 pointer-events: none;
47 }
48
49 .cube-layer {
50 position: absolute;
51 width: 100%;
52 height: 100%;
53 border: 1px solid var(--cube-color);
54 transform-style: preserve-3d;
55 }
56
57 /* Central Sphere of Rings */
58 .sphere-container {
59 position: absolute;
60 top: 50%;
61 left: 50%;
62 width: 0;
63 height: 0;
64 transform-style: preserve-3d;
65 animation: global-rotate 10s linear infinite;
66 }
67
68 .ring {
69 position: absolute;
70 border-radius: 50%;
71 border: 1.5px solid transparent;
72 transform-style: preserve-3d;
73 box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
74 animation: ring-pulse 4s ease-in-out infinite;
75 }
76
77 /* Animation keyframes */
78 @keyframes global-rotate {
79 0% { transform: rotateY(0deg) rotateX(0deg); }
80 100% { transform: rotateY(360deg) rotateX(20deg); }
81 }
82
83 @keyframes ring-pulse {
84 0%, 100% { opacity: 0.6; transform: translate(-50%, -50%) scale(1); }
85 50% { opacity: 1; transform: translate(-50%, -50%) scale(1.05); }
86 }
87
88 /* The split animation at 3s as seen in video */
89 .split-anim {
90 animation: split-effect 4s ease-in-out infinite;
91 }
92
93 @keyframes split-effect {
94 0%, 65% { transform: translateX(0); opacity: 1; }
95 75% { transform: translateX(-60px); opacity: 0.8; }
96 85% { transform: translateX(60px); opacity: 0.8; }
97 95%, 100% { transform: translateX(0); opacity: 1; }
98 }
99
100 .group-left { animation: split-left 4s ease-in-out infinite; }
101 .group-right { animation: split-right 4s ease-in-out infinite; }
102
103 @keyframes split-left {
104 0%, 70% { transform: translateX(0) scale(1); }
105 80%, 90% { transform: translateX(-80px) scale(0.8); }
106 100% { transform: translateX(0) scale(1); }
107 }
108
109 @keyframes split-right {
110 0%, 70% { transform: translateX(0) scale(1); }
111 80%, 90% { transform: translateX(80px) scale(0.8); }
112 100% { transform: translateX(0) scale(1); }
113 }
114
115 </style>
116</head>
117<body>
118
119 <div class="container" id="mainScene">
120 <!-- Cube layers created via JS -->
121 <div class="wireframe-cube" id="cubeContainer"></div>
122
123 <!-- Sphere groups for splitting effect -->
124 <div class="sphere-container">
125 <div id="groupLeft" class="group-left" style="position: absolute; transform-style: preserve-3d;"></div>
126 <div id="groupRight" class="group-right" style="position: absolute; transform-style: preserve-3d;"></div>
127 </div>
128 </div>
129
130 <script>
131 const cubeContainer = document.getElementById('cubeContainer');
132 const groupLeft = document.getElementById('groupLeft');
133 const groupRight = document.getElementById('groupRight');
134
135 // Create the wireframe cube effect (stack of squares)
136 for (let i = 0; i < 15; i++) {
137 const layer = document.createElement('div');
138 layer.className = 'cube-layer';
139 // Space them along Z axis to create depth
140 layer.style.transform = `translateZ(${(i - 7) * 20}px)`;
141 cubeContainer.appendChild(layer);
142 }
143
144 // Create the Sphere Rings
145 const ringCount = 24;
146 const sphereRadius = 100;
147
148 for (let i = 0; i < ringCount; i++) {
149 const ring = document.createElement('div');
150 ring.className = 'ring';
151
152 // Calculate size based on position in sphere
153 const angle = (i / ringCount) * Math.PI;
154 const currentRadius = Math.sin(angle) * sphereRadius;
155 const zPos = Math.cos(angle) * sphereRadius;
156
157 ring.style.width = `${currentRadius * 2}px`;
158 ring.style.height = `${currentRadius * 2}px`;
159 ring.style.transform = `translate(-50%, -50%) translateZ(${zPos}px)`;
160
161 // Color interpolation
162 const colorProgress = i / ringCount;
163 let color;
164 if (colorProgress < 0.3) color = 'var(--ring-cyan)';
165 else if (colorProgress < 0.7) color = 'var(--ring-blue)';
166 else color = 'var(--ring-green)';
167
168 ring.style.borderColor = color;
169 ring.style.boxShadow = `0 0 15px ${color}, inset 0 0 5px ${color}`;
170 ring.style.animationDelay = `${i * 0.1}s`;
171
172 // Assign to left or right group for the split animation
173 if (i < ringCount / 2) {
174 groupLeft.appendChild(ring);
175 } else {
176 groupRight.appendChild(ring);
177 }
178 }
179
180 // Add subtle mouse parallax for extra polish
181 document.addEventListener('mousemove', (e) => {
182 const xAxis = (window.innerWidth / 2 - e.pageX) / 25;
183 const yAxis = (window.innerHeight / 2 - e.pageY) / 25;
184 document.getElementById('mainScene').style.transform = `rotateX(${-25 + yAxis}deg) rotateY(${-35 + xAxis}deg)`;
185 });
186 </script>
187</body>
188</html>