HI7RAI commited on
Commit
660ed8f
·
verified ·
1 Parent(s): 49cca39

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +0 -468
index.html CHANGED
@@ -1,468 +0,0 @@
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>Crypto Live 3D | Immersive Charts</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com">
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
- <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;500;700&display=swap" rel="stylesheet">
10
- <!-- Import Three.js from CDN -->
11
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
12
- <!-- Import OrbitControls -->
13
- <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
14
-
15
- <style>
16
- :root {
17
- --primary: #00f2ff;
18
- --danger: #ff0055;
19
- --bg: #050505;
20
- --glass: rgba(255, 255, 255, 0.05);
21
- --glass-border: rgba(255, 255, 255, 0.1);
22
- --text: #ffffff;
23
- --text-dim: #888888;
24
- }
25
-
26
- * {
27
- margin: 0;
28
- padding: 0;
29
- box-sizing: border-box;
30
- }
31
-
32
- body {
33
- background-color: var(--bg);
34
- color: var(--text);
35
- font-family: 'Space Grotesk', sans-serif;
36
- overflow: hidden; /* Prevent scroll, canvas handles it */
37
- height: 100vh;
38
- width: 100vw;
39
- }
40
-
41
- /* --- 3D Canvas Container --- */
42
- #canvas-container {
43
- position: absolute;
44
- top: 0;
45
- left: 0;
46
- width: 100%;
47
- height: 100%;
48
- z-index: 1;
49
- background: radial-gradient(circle at center, #1a1a2e 0%, #000000 100%);
50
- }
51
-
52
- /* --- UI Overlay Layer --- */
53
- .ui-layer {
54
- position: absolute;
55
- top: 0;
56
- left: 0;
57
- width: 100%;
58
- height: 100%;
59
- z-index: 10;
60
- pointer-events: none; /* Let clicks pass through to 3D canvas */
61
- display: flex;
62
- flex-direction: column;
63
- justify-content: space-between;
64
- padding: 2rem;
65
- }
66
-
67
- /* --- Header --- */
68
- header {
69
- display: flex;
70
- justify-content: space-between;
71
- align-items: center;
72
- pointer-events: auto;
73
- }
74
-
75
- .brand {
76
- font-size: 1.5rem;
77
- font-weight: 700;
78
- letter-spacing: 2px;
79
- background: linear-gradient(90deg, #fff, var(--primary));
80
- -webkit-background-clip: text;
81
- -webkit-text-fill-color: transparent;
82
- }
83
-
84
- .anycoder-link {
85
- font-size: 0.9rem;
86
- color: var(--text-dim);
87
- text-decoration: none;
88
- border-bottom: 1px solid var(--text-dim);
89
- transition: 0.3s;
90
- }
91
-
92
- .anycoder-link:hover {
93
- color: var(--primary);
94
- border-color: var(--primary);
95
- }
96
-
97
- /* --- Controls & Stats --- */
98
- .controls-container {
99
- display: flex;
100
- flex-wrap: wrap;
101
- gap: 2rem;
102
- align-items: flex-end;
103
- pointer-events: auto;
104
- }
105
-
106
- .stat-card {
107
- background: var(--glass);
108
- backdrop-filter: blur(12px);
109
- -webkit-backdrop-filter: blur(12px);
110
- border: 1px solid var(--glass-border);
111
- padding: 1.5rem;
112
- border-radius: 16px;
113
- min-width: 200px;
114
- box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
115
- transition: transform 0.3s ease;
116
- }
117
-
118
- .stat-card:hover {
119
- transform: translateY(-5px);
120
- border-color: var(--primary);
121
- }
122
-
123
- .label {
124
- font-size: 0.8rem;
125
- color: var(--text-dim);
126
- text-transform: uppercase;
127
- letter-spacing: 1px;
128
- margin-bottom: 0.5rem;
129
- }
130
-
131
- .value {
132
- font-size: 2rem;
133
- font-weight: 700;
134
- }
135
-
136
- .value.positive { color: #00ff88; text-shadow: 0 0 10px rgba(0, 255, 136, 0.4); }
137
- .value.negative { color: var(--danger); text-shadow: 0 0 10px rgba(255, 0, 85, 0.4); }
138
-
139
- /* --- Select Dropdown --- */
140
- .select-wrapper {
141
- position: relative;
142
- }
143
-
144
- select {
145
- background: var(--glass);
146
- color: white;
147
- border: 1px solid var(--glass-border);
148
- padding: 1rem 3rem 1rem 1.5rem;
149
- border-radius: 12px;
150
- font-family: 'Space Grotesk', sans-serif;
151
- font-size: 1rem;
152
- outline: none;
153
- cursor: pointer;
154
- appearance: none;
155
- width: 200px;
156
- }
157
-
158
- .select-arrow {
159
- position: absolute;
160
- right: 15px;
161
- top: 50%;
162
- transform: translateY(-50%);
163
- pointer-events: none;
164
- color: var(--primary);
165
- }
166
-
167
- /* --- Loading Indicator --- */
168
- .loader {
169
- position: absolute;
170
- top: 50%;
171
- left: 50%;
172
- transform: translate(-50%, -50%);
173
- z-index: 20;
174
- pointer-events: none;
175
- font-size: 1.2rem;
176
- color: var(--primary);
177
- opacity: 0;
178
- transition: opacity 0.3s;
179
- }
180
- .loader.active { opacity: 1; }
181
-
182
- /* --- Responsive --- */
183
- @media (max-width: 768px) {
184
- .ui-layer { padding: 1rem; }
185
- .controls-container { flex-direction: column; align-items: stretch; gap: 1rem; }
186
- .stat-card { width: 100%; }
187
- .value { font-size: 1.5rem; }
188
- header { flex-direction: column; gap: 10px; align-items: flex-start; }
189
- }
190
- </style>
191
- </head>
192
- <body>
193
-
194
- <!-- 3D Canvas -->
195
- <div id="canvas-container"></div>
196
-
197
- <!-- UI Overlay -->
198
- <div class="ui-layer">
199
- <header>
200
- <div class="brand">CRYPTO<span style="color:var(--primary)">3D</span></div>
201
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
202
- </header>
203
-
204
- <div class="controls-container">
205
- <!-- Selection -->
206
- <div class="select-wrapper">
207
- <select id="coin-select">
208
- <option value="bitcoin">Bitcoin (BTC)</option>
209
- <option value="ethereum">Ethereum (ETH)</option>
210
- <option value="solana">Solana (SOL)</option>
211
- <option value="cardano">Cardano (ADA)</option>
212
- <option value="ripple">XRP (XRP)</option>
213
- <option value="dogecoin">Dogecoin (DOGE)</option>
214
- </select>
215
- <span class="select-arrow">▼</span>
216
- </div>
217
-
218
- <!-- Price Display -->
219
- <div class="stat-card">
220
- <div class="label">Current Price</div>
221
- <div class="value" id="current-price">Loading...</div>
222
- </div>
223
-
224
- <!-- 24h Change -->
225
- <div class="stat-card">
226
- <div class="label">24h Change</div>
227
- <div class="value" id="price-change">Loading...</div>
228
- </div>
229
- </div>
230
- </div>
231
-
232
- <div class="loader" id="loader">Fetching Live Data...</div>
233
-
234
- <script>
235
- // --- Configuration ---
236
- const sceneConfig = {
237
- bgColor: 0x050505,
238
- lineColor: 0x00f2ff,
239
- gridColor: 0x222222
240
- };
241
-
242
- // --- Three.js Variables ---
243
- let scene, camera, renderer, controls;
244
- let chartMesh, gridHelper, particles;
245
- let animationId;
246
-
247
- // --- Data State ---
248
- let currentCoin = 'bitcoin';
249
- let chartData = [];
250
-
251
- // --- Initialization ---
252
- function init() {
253
- const container = document.getElementById('canvas-container');
254
-
255
- // 1. Scene
256
- scene = new THREE.Scene();
257
- scene.background = new THREE.Color(sceneConfig.bgColor);
258
- scene.fog = new THREE.FogExp2(sceneConfig.bgColor, 0.03);
259
-
260
- // 2. Camera
261
- camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
262
- camera.position.set(0, 15, 30);
263
-
264
- // 3. Renderer
265
- renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
266
- renderer.setSize(window.innerWidth, window.innerHeight);
267
- renderer.setPixelRatio(window.devicePixelRatio);
268
- container.appendChild(renderer.domElement);
269
-
270
- // 4. Controls
271
- controls = new THREE.OrbitControls(camera, renderer.domElement);
272
- controls.enableDamping = true;
273
- controls.dampingFactor = 0.05;
274
- controls.autoRotate = true;
275
- controls.autoRotateSpeed = 1.0;
276
- controls.maxPolarAngle = Math.PI / 2; // Don't go below ground
277
-
278
- // 5. Lights
279
- const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
280
- scene.add(ambientLight);
281
-
282
- const pointLight = new THREE.PointLight(sceneConfig.lineColor, 1, 100);
283
- pointLight.position.set(0, 20, 10);
284
- scene.add(pointLight);
285
-
286
- // 6. Helpers
287
- gridHelper = new THREE.GridHelper(100, 50, sceneConfig.lineColor, sceneConfig.gridColor);
288
- scene.add(gridHelper);
289
-
290
- // 7. Background Particles
291
- addParticles();
292
-
293
- // 8. Event Listeners
294
- window.addEventListener('resize', onWindowResize);
295
- document.getElementById('coin-select').addEventListener('change', (e) => {
296
- currentCoin = e.target.value;
297
- fetchCryptoData();
298
- });
299
-
300
- // Initial Load
301
- fetchCryptoData();
302
- animate();
303
- }
304
-
305
- // --- Particle System ---
306
- function addParticles() {
307
- const geometry = new THREE.BufferGeometry();
308
- const count = 1000;
309
- const positions = new Float32Array(count * 3);
310
-
311
- for(let i = 0; i < count * 3; i++) {
312
- positions[i] = (Math.random() - 0.5) * 100;
313
- }
314
-
315
- geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
316
- const material = new THREE.PointsMaterial({
317
- size: 0.1,
318
- color: sceneConfig.lineColor,
319
- transparent: true,
320
- opacity: 0.5
321
- });
322
-
323
- particles = new THREE.Points(geometry, material);
324
- scene.add(particles);
325
- }
326
-
327
- // --- API Data Fetching ---
328
- async function fetchCryptoData() {
329
- const loader = document.getElementById('loader');
330
- loader.classList.add('active');
331
-
332
- try {
333
- // Fetch market chart data (price history)
334
- const response = await fetch(`https://api.coingecko.com/api/v3/coins/${currentCoin}/market_chart?vs_currency=usd&days=1&interval=hourly`);
335
- const data = await response.json();
336
-
337
- if(!data.prices) throw new Error("No data");
338
-
339
- chartData = data.prices; // Array of [timestamp, price]
340
-
341
- updateUI(chartData);
342
- generate3DChart(chartData);
343
-
344
- } catch (error) {
345
- console.error("API Error:", error);
346
- // Fallback for demo if API limit reached
347
- simulateFallbackData();
348
- } finally {
349
- loader.classList.remove('active');
350
- }
351
- }
352
-
353
- function simulateFallbackData() {
354
- // Generate fake data if API fails
355
- let fakeData = [];
356
- let price = 30000;
357
- let now = Date.now();
358
- for(let i=0; i<100; i++) {
359
- price = price + (Math.random() - 0.5) * 500;
360
- fakeData.push([now - (100-i)*360000, price]);
361
- }
362
- chartData = fakeData;
363
- updateUI(chartData);
364
- generate3DChart(chartData);
365
- }
366
-
367
- // --- UI Updates ---
368
- function updateUI(data) {
369
- const currentPrice = data[data.length - 1][1];
370
- const previousPrice = data[0][1];
371
- const change = ((currentPrice - previousPrice) / previousPrice) * 100;
372
-
373
- const priceEl = document.getElementById('current-price');
374
- const changeEl = document.getElementById('price-change');
375
-
376
- priceEl.innerText = `$${currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
377
-
378
- changeEl.innerText = `${change.toFixed(2)}%`;
379
- changeEl.className = change >= 0 ? 'value positive' : 'value negative';
380
-
381
- // Change chart color based on trend
382
- const color = change >= 0 ? 0x00ff88 : 0xff0055;
383
- sceneConfig.lineColor = color;
384
- }
385
-
386
- // --- 3D Chart Generation ---
387
- function generate3DChart(data) {
388
- // Remove old chart
389
- if (chartMesh) {
390
- scene.remove(chartMesh);
391
- chartMesh.geometry.dispose();
392
- chartMesh.material.dispose();
393
- }
394
-
395
- // Process data
396
- const points = [];
397
- const maxPrice = Math.max(...data.map(d => d[1]));
398
- const minPrice = Math.min(...data.map(d => d[1]));
399
- const priceRange = maxPrice - minPrice || 1;
400
-
401
- // Normalize data to fit in 3D space
402
- data.forEach((point, index) => {
403
- const x = (index / data.length) * 40 - 20; // Spread across X axis (-20 to 20)
404
- const y = ((point[1] - minPrice) / priceRange) * 10; // Height based on price
405
- const z = 0;
406
- points.push(new THREE.Vector3(x, y, z));
407
- });
408
-
409
- // Create Curve
410
- const curve = new THREE.CatmullRomCurve3(points);
411
-
412
- // Create Tube Geometry
413
- const geometry = new THREE.TubeGeometry(curve, 100, 0.4, 8, false);
414
-
415
- // Material (Glowing Neon)
416
- const material = new THREE.MeshPhongMaterial({
417
- color: sceneConfig.lineColor,
418
- emissive: sceneConfig.lineColor,
419
- emissiveIntensity: 0.5,
420
- shininess: 100
421
- });
422
-
423
- chartMesh = new THREE.Mesh(geometry, material);
424
-
425
- // Add vertical lines (Candlestick-like effect simplified)
426
- const lineMaterial = new THREE.LineBasicMaterial({
427
- color: sceneConfig.lineColor,
428
- transparent: true,
429
- opacity: 0.3
430
- });
431
-
432
- scene.add(chartMesh);
433
- }
434
-
435
- // --- Animation Loop ---
436
- function animate() {
437
- requestAnimationFrame(animate);
438
-
439
- // Rotate particles slowly
440
- if(particles) {
441
- particles.rotation.y += 0.001;
442
- }
443
-
444
- // Update controls
445
- controls.update();
446
-
447
- // Pulse effect on the chart mesh
448
- if(chartMesh) {
449
- const time = Date.now() * 0.001;
450
- chartMesh.material.emissiveIntensity = 0.5 + Math.sin(time * 2) * 0.2;
451
- }
452
-
453
- renderer.render(scene, camera);
454
- }
455
-
456
- // --- Window Resize Handler ---
457
- function onWindowResize() {
458
- camera.aspect = window.innerWidth / window.innerHeight;
459
- camera.updateProjectionMatrix();
460
- renderer.setSize(window.innerWidth, window.innerHeight);
461
- }
462
-
463
- // Start App
464
- init();
465
-
466
- </script>
467
- </body>
468
- </html>