13Aluminium commited on
Commit
eed70d8
·
verified ·
1 Parent(s): cd2f9ed

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +422 -19
index.html CHANGED
@@ -1,19 +1,422 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Word Embedding Visualization</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');
9
+
10
+ body, html {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow: hidden;
14
+ font-family: 'Inter', sans-serif;
15
+ background: radial-gradient(ellipse at center, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
16
+ }
17
+
18
+ #info {
19
+ position: absolute;
20
+ top: 20px;
21
+ left: 20px;
22
+ background: rgba(0, 0, 0, 0.8);
23
+ backdrop-filter: blur(10px);
24
+ color: #fff;
25
+ padding: 16px 20px;
26
+ border-radius: 12px;
27
+ font-size: 14px;
28
+ border: 1px solid rgba(255, 255, 255, 0.1);
29
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
30
+ }
31
+
32
+ #info p {
33
+ margin: 0 0 8px 0;
34
+ font-weight: 400;
35
+ }
36
+
37
+ #info p:last-child {
38
+ margin-bottom: 0;
39
+ }
40
+
41
+ #countDisplay {
42
+ color: #64ffda;
43
+ font-weight: 600;
44
+ }
45
+
46
+ #wordInfo {
47
+ position: absolute;
48
+ bottom: 20px;
49
+ left: 20px;
50
+ background: rgba(0, 0, 0, 0.9);
51
+ backdrop-filter: blur(15px);
52
+ color: #fff;
53
+ padding: 20px 24px;
54
+ border-radius: 12px;
55
+ display: none;
56
+ font-size: 14px;
57
+ border: 1px solid rgba(100, 255, 218, 0.3);
58
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
59
+ min-width: 200px;
60
+ }
61
+
62
+ #wordInfo strong {
63
+ color: #64ffda;
64
+ font-size: 18px;
65
+ font-weight: 600;
66
+ display: block;
67
+ margin-bottom: 12px;
68
+ }
69
+
70
+ #wordInfo .coord {
71
+ margin: 4px 0;
72
+ font-family: 'Courier New', monospace;
73
+ color: #b0bec5;
74
+ }
75
+
76
+ canvas {
77
+ display: block;
78
+ cursor: grab;
79
+ }
80
+
81
+ canvas:active {
82
+ cursor: grabbing;
83
+ }
84
+
85
+ #loading {
86
+ position: absolute;
87
+ top: 50%;
88
+ left: 50%;
89
+ transform: translate(-50%, -50%);
90
+ color: #64ffda;
91
+ font-size: 18px;
92
+ font-weight: 500;
93
+ }
94
+
95
+ .pulse {
96
+ animation: pulse 2s infinite;
97
+ }
98
+
99
+ @keyframes pulse {
100
+ 0% { opacity: 0.6; }
101
+ 50% { opacity: 1; }
102
+ 100% { opacity: 0.6; }
103
+ }
104
+ </style>
105
+ </head>
106
+ <body>
107
+ <div id="loading" class="pulse">Loading word embeddings...</div>
108
+ <div id="info" style="display: none;">
109
+ <p>Visualizing <span id="countDisplay"></span> most frequent words</p>
110
+ <p><strong>Controls:</strong> Rotate: drag • Zoom: scroll • Pan: right-click + drag</p>
111
+ <p>Click any word sphere to inspect details</p>
112
+ </div>
113
+ <div id="wordInfo"></div>
114
+
115
+ <script type="importmap">
116
+ {
117
+ "imports": {
118
+ "three": "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.module.min.js",
119
+ "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
120
+ }
121
+ }
122
+ </script>
123
+ <script type="module">
124
+ import * as THREE from 'three';
125
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
126
+
127
+ const MAX_WORDS = 4000;
128
+
129
+ let scene, camera, renderer, controls;
130
+ let raycaster = new THREE.Raycaster();
131
+ let mouse = new THREE.Vector2();
132
+ let spheres = [];
133
+ let selectedSphere = null;
134
+ let originalMaterials = new Map();
135
+ let hoveredSphere = null;
136
+
137
+ init();
138
+ animate();
139
+
140
+ function init() {
141
+ document.getElementById('countDisplay').textContent = MAX_WORDS.toLocaleString();
142
+
143
+ // Scene setup with better background
144
+ scene = new THREE.Scene();
145
+ scene.background = new THREE.Color(0x0a0a0a);
146
+ scene.fog = new THREE.Fog(0x0a0a0a, 50, 200);
147
+
148
+ // Camera with better initial position
149
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
150
+ camera.position.set(15, 10, 25);
151
+
152
+ // Renderer with enhanced settings
153
+ renderer = new THREE.WebGLRenderer({
154
+ antialias: true,
155
+ alpha: true,
156
+ powerPreference: "high-performance"
157
+ });
158
+ renderer.setSize(window.innerWidth, window.innerHeight);
159
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
160
+ renderer.shadowMap.enabled = true;
161
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
162
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
163
+ renderer.toneMappingExposure = 1.2;
164
+ document.body.appendChild(renderer.domElement);
165
+
166
+ // Enhanced controls
167
+ controls = new OrbitControls(camera, renderer.domElement);
168
+ controls.enableDamping = true;
169
+ controls.dampingFactor = 0.05;
170
+ controls.screenSpacePanning = false;
171
+ controls.minDistance = 5;
172
+ controls.maxDistance = 100;
173
+ controls.maxPolarAngle = Math.PI;
174
+
175
+ // Event listeners
176
+ window.addEventListener('resize', onResize);
177
+ window.addEventListener('pointermove', onPointerMove, false);
178
+ window.addEventListener('pointerdown', onClick, false);
179
+
180
+ // Load data
181
+ fetch('word_vectors_3d.json')
182
+ .then(r => {
183
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
184
+ return r.json();
185
+ })
186
+ .then(data => {
187
+ const subset = data.slice(0, MAX_WORDS);
188
+ createEnhancedSpheres(subset);
189
+ document.getElementById('loading').style.display = 'none';
190
+ document.getElementById('info').style.display = 'block';
191
+ })
192
+ .catch(e => {
193
+ console.error(e);
194
+ document.getElementById('loading').textContent = 'Error loading data. Make sure word_vectors_3d.json exists.';
195
+ });
196
+ }
197
+
198
+ function createEnhancedSpheres(data) {
199
+ // Compute bounds and normalize
200
+ let mins = { x: Infinity, y: Infinity, z: Infinity };
201
+ let maxs = { x: -Infinity, y: -Infinity, z: -Infinity };
202
+
203
+ data.forEach(p => {
204
+ mins.x = Math.min(mins.x, p.x);
205
+ mins.y = Math.min(mins.y, p.y);
206
+ mins.z = Math.min(mins.z, p.z);
207
+ maxs.x = Math.max(maxs.x, p.x);
208
+ maxs.y = Math.max(maxs.y, p.y);
209
+ maxs.z = Math.max(maxs.z, p.z);
210
+ });
211
+
212
+ // Scale factor for better visualization
213
+ const scale = 40;
214
+
215
+ // Create instanced geometry for better performance
216
+ const radius = 0.15;
217
+ const geometry = new THREE.SphereGeometry(radius, 12, 8);
218
+
219
+ // Create particle system for background effect
220
+ createStarField();
221
+
222
+ let group = new THREE.Group();
223
+
224
+ data.forEach((p, index) => {
225
+ // Normalize coordinates
226
+ const x = ((p.x - mins.x) / (maxs.x - mins.x) - 0.5) * scale;
227
+ const y = ((p.y - mins.y) / (maxs.y - mins.y) - 0.5) * scale;
228
+ const z = ((p.z - mins.z) / (maxs.z - mins.z) - 0.5) * scale;
229
+
230
+ // Color based on position with enhanced palette
231
+ const hue = (p.x - mins.x) / (maxs.x - mins.x);
232
+ const saturation = 0.7 + 0.3 * ((p.y - mins.y) / (maxs.y - mins.y));
233
+ const lightness = 0.4 + 0.4 * ((p.z - mins.z) / (maxs.z - mins.z));
234
+
235
+ const color = new THREE.Color().setHSL(hue * 0.8 + 0.1, saturation, lightness);
236
+
237
+ // Enhanced material with emissive properties
238
+ const material = new THREE.MeshPhysicalMaterial({
239
+ color: color,
240
+ emissive: color.clone().multiplyScalar(0.1),
241
+ metalness: 0.1,
242
+ roughness: 0.4,
243
+ clearcoat: 0.3,
244
+ clearcoatRoughness: 0.2,
245
+ transparent: true,
246
+ opacity: 0.8
247
+ });
248
+
249
+ const mesh = new THREE.Mesh(geometry, material);
250
+ mesh.position.set(x, y, z);
251
+ mesh.userData = { ...p, index };
252
+ mesh.castShadow = true;
253
+ mesh.receiveShadow = true;
254
+
255
+ // Store original material
256
+ originalMaterials.set(mesh, material.clone());
257
+
258
+ spheres.push(mesh);
259
+ group.add(mesh);
260
+ });
261
+
262
+ scene.add(group);
263
+ setupLighting();
264
+ }
265
+
266
+ function createStarField() {
267
+ const starsGeometry = new THREE.BufferGeometry();
268
+ const starsMaterial = new THREE.PointsMaterial({
269
+ color: 0x888888,
270
+ size: 0.5,
271
+ transparent: true,
272
+ opacity: 0.3
273
+ });
274
+
275
+ const starsVertices = [];
276
+ for (let i = 0; i < 1000; i++) {
277
+ const x = (Math.random() - 0.5) * 200;
278
+ const y = (Math.random() - 0.5) * 200;
279
+ const z = (Math.random() - 0.5) * 200;
280
+ starsVertices.push(x, y, z);
281
+ }
282
+
283
+ starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
284
+ const stars = new THREE.Points(starsGeometry, starsMaterial);
285
+ scene.add(stars);
286
+ }
287
+
288
+ function setupLighting() {
289
+ // Ambient light for overall illumination
290
+ const ambientLight = new THREE.AmbientLight(0x404040, 0.4);
291
+ scene.add(ambientLight);
292
+
293
+ // Main directional light
294
+ const mainLight = new THREE.DirectionalLight(0xffffff, 0.8);
295
+ mainLight.position.set(20, 20, 20);
296
+ mainLight.castShadow = true;
297
+ mainLight.shadow.mapSize.width = 2048;
298
+ mainLight.shadow.mapSize.height = 2048;
299
+ scene.add(mainLight);
300
+
301
+ // Fill light
302
+ const fillLight = new THREE.DirectionalLight(0x64ffda, 0.3);
303
+ fillLight.position.set(-20, -20, -20);
304
+ scene.add(fillLight);
305
+
306
+ // Rim light
307
+ const rimLight = new THREE.DirectionalLight(0xff6b6b, 0.2);
308
+ rimLight.position.set(0, 20, -20);
309
+ scene.add(rimLight);
310
+ }
311
+
312
+ function onPointerMove(event) {
313
+ mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
314
+ mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
315
+
316
+ raycaster.setFromCamera(mouse, camera);
317
+ const intersects = raycaster.intersectObjects(spheres);
318
+
319
+ if (intersects.length > 0) {
320
+ renderer.domElement.style.cursor = 'pointer';
321
+ } else {
322
+ renderer.domElement.style.cursor = 'grab';
323
+ }
324
+ }
325
+
326
+ function onClick(event) {
327
+ mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
328
+ mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
329
+
330
+ raycaster.setFromCamera(mouse, camera);
331
+ const intersects = raycaster.intersectObjects(spheres);
332
+
333
+ // Reset previous selection
334
+ if (selectedSphere) {
335
+ resetSphereAppearance(selectedSphere);
336
+ }
337
+
338
+ const wordInfo = document.getElementById('wordInfo');
339
+
340
+ if (intersects.length > 0) {
341
+ selectedSphere = intersects[0].object;
342
+ const data = selectedSphere.userData;
343
+
344
+ // Highlight selected sphere
345
+ highlightSphere(selectedSphere, 'selected');
346
+
347
+ // Show word info with enhanced styling
348
+ wordInfo.innerHTML = `
349
+ <strong>${data.word}</strong>
350
+ <div class="coord">x: ${data.x.toFixed(3)}</div>
351
+ <div class="coord">y: ${data.y.toFixed(3)}</div>
352
+ <div class="coord">z: ${data.z.toFixed(3)}</div>
353
+ <div style="margin-top: 8px; color: #90a4ae; font-size: 12px;">
354
+ Index: ${data.index + 1} / ${MAX_WORDS.toLocaleString()}
355
+ </div>
356
+ `;
357
+ wordInfo.style.display = 'block';
358
+ } else {
359
+ selectedSphere = null;
360
+ wordInfo.style.display = 'none';
361
+ }
362
+ }
363
+
364
+ function highlightSphere(sphere, type) {
365
+ const material = sphere.material;
366
+
367
+ if (type === 'selected') {
368
+ material.emissive.setHex(0x64ffda);
369
+ material.emissiveIntensity = 0.5;
370
+ sphere.scale.setScalar(1.5);
371
+
372
+ // Add pulsing animation
373
+ const originalScale = sphere.scale.clone();
374
+ function pulse() {
375
+ if (sphere === selectedSphere) {
376
+ sphere.scale.multiplyScalar(1.02);
377
+ if (sphere.scale.x > originalScale.x * 1.1) {
378
+ sphere.scale.copy(originalScale);
379
+ }
380
+ requestAnimationFrame(pulse);
381
+ }
382
+ }
383
+ pulse();
384
+ }
385
+ }
386
+
387
+ function resetSphereAppearance(sphere) {
388
+ const originalMaterial = originalMaterials.get(sphere);
389
+ if (originalMaterial) {
390
+ sphere.material.emissive.copy(originalMaterial.emissive);
391
+ sphere.material.emissiveIntensity = originalMaterial.emissiveIntensity || 0.1;
392
+ }
393
+ sphere.scale.setScalar(1);
394
+ }
395
+
396
+ function animateCamera(targetPosition, lookAtPosition) {
397
+ // Removed smooth camera movement function
398
+ }
399
+
400
+ function onResize() {
401
+ camera.aspect = window.innerWidth / window.innerHeight;
402
+ camera.updateProjectionMatrix();
403
+ renderer.setSize(window.innerWidth, window.innerHeight);
404
+ }
405
+
406
+ function animate() {
407
+ requestAnimationFrame(animate);
408
+
409
+ // Gentle rotation of the star field
410
+ if (scene.children.length > 0) {
411
+ const stars = scene.children.find(child => child.type === 'Points');
412
+ if (stars) {
413
+ stars.rotation.y += 0.0005;
414
+ }
415
+ }
416
+
417
+ controls.update();
418
+ renderer.render(scene, camera);
419
+ }
420
+ </script>
421
+ </body>
422
+ </html>