r0cketboy commited on
Commit
63c6c50
·
verified ·
1 Parent(s): 00c98ec

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +437 -19
index.html CHANGED
@@ -1,19 +1,437 @@
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="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Ferrofluid Audio Visualizer</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ background: #000;
16
+ font-family: 'Arial', sans-serif;
17
+ overflow: hidden;
18
+ color: white;
19
+ }
20
+
21
+ .header {
22
+ position: absolute;
23
+ top: 0;
24
+ width: 100%;
25
+ padding: 20px;
26
+ z-index: 100;
27
+ display: flex;
28
+ justify-content: space-between;
29
+ align-items: center;
30
+ background: rgba(0, 0, 0, 0.5);
31
+ }
32
+
33
+ .header h1 {
34
+ font-size: 1.5rem;
35
+ }
36
+
37
+ .anycoder-link {
38
+ color: #00ff88;
39
+ text-decoration: none;
40
+ font-size: 0.9rem;
41
+ transition: color 0.3s;
42
+ }
43
+
44
+ .anycoder-link:hover {
45
+ color: #00cc66;
46
+ }
47
+
48
+ .container {
49
+ position: relative;
50
+ width: 100vw;
51
+ height: 100vh;
52
+ display: flex;
53
+ justify-content: center;
54
+ align-items: center;
55
+ }
56
+
57
+ #visualizer {
58
+ position: absolute;
59
+ top: 0;
60
+ left: 0;
61
+ width: 100%;
62
+ height: 100%;
63
+ }
64
+
65
+ .controls {
66
+ position: absolute;
67
+ bottom: 30px;
68
+ left: 50%;
69
+ transform: translateX(-50%);
70
+ z-index: 100;
71
+ background: rgba(0, 0, 0, 0.7);
72
+ padding: 20px;
73
+ border-radius: 10px;
74
+ display: flex;
75
+ flex-direction: column;
76
+ gap: 15px;
77
+ align-items: center;
78
+ min-width: 300px;
79
+ }
80
+
81
+ .file-input-container {
82
+ display: flex;
83
+ flex-direction: column;
84
+ align-items: center;
85
+ gap: 10px;
86
+ }
87
+
88
+ .file-input-label {
89
+ background: #00ff88;
90
+ color: black;
91
+ padding: 10px 20px;
92
+ border-radius: 5px;
93
+ cursor: pointer;
94
+ font-weight: bold;
95
+ transition: background 0.3s;
96
+ }
97
+
98
+ .file-input-label:hover {
99
+ background: #00cc66;
100
+ }
101
+
102
+ #audioFile {
103
+ display: none;
104
+ }
105
+
106
+ .button-group {
107
+ display: flex;
108
+ gap: 10px;
109
+ }
110
+
111
+ button {
112
+ background: #333;
113
+ color: white;
114
+ border: none;
115
+ padding: 10px 20px;
116
+ border-radius: 5px;
117
+ cursor: pointer;
118
+ transition: background 0.3s;
119
+ }
120
+
121
+ button:hover {
122
+ background: #555;
123
+ }
124
+
125
+ button:disabled {
126
+ background: #222;
127
+ color: #666;
128
+ cursor: not-allowed;
129
+ }
130
+
131
+ .slider-container {
132
+ display: flex;
133
+ align-items: center;
134
+ gap: 10px;
135
+ width: 100%;
136
+ }
137
+
138
+ .slider-container label {
139
+ min-width: 80px;
140
+ }
141
+
142
+ input[type="range"] {
143
+ flex: 1;
144
+ height: 5px;
145
+ background: #333;
146
+ outline: none;
147
+ border-radius: 5px;
148
+ }
149
+
150
+ .status {
151
+ font-size: 0.9rem;
152
+ color: #00ff88;
153
+ }
154
+
155
+ @media (max-width: 768px) {
156
+ .controls {
157
+ width: 90%;
158
+ min-width: unset;
159
+ }
160
+
161
+ .header h1 {
162
+ font-size: 1.2rem;
163
+ }
164
+
165
+ .button-group {
166
+ flex-direction: column;
167
+ width: 100%;
168
+ }
169
+
170
+ button {
171
+ width: 100%;
172
+ }
173
+ }
174
+ </style>
175
+ </head>
176
+ <body>
177
+ <div class="header">
178
+ <h1>Ferrofluid Audio Visualizer</h1>
179
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">Built with anycoder</a>
180
+ </div>
181
+
182
+ <div class="container">
183
+ <canvas id="visualizer"></canvas>
184
+
185
+ <div class="controls">
186
+ <div class="file-input-container">
187
+ <label for="audioFile" class="file-input-label">Audio Datei auswählen</label>
188
+ <input type="file" id="audioFile" accept="audio/*">
189
+ <div class="status" id="fileStatus">Keine Datei ausgewählt</div>
190
+ </div>
191
+
192
+ <div class="slider-container">
193
+ <label for="sensitivity">Empfindlichkeit:</label>
194
+ <input type="range" id="sensitivity" min="1" max="10" value="5">
195
+ </div>
196
+
197
+ <div class="slider-container">
198
+ <label for="smoothness">Glättung:</label>
199
+ <input type="range" id="smoothness" min="1" max="10" value="3">
200
+ </div>
201
+
202
+ <div class="button-group">
203
+ <button id="playBtn" disabled>Abspielen</button>
204
+ <button id="pauseBtn" disabled>Pause</button>
205
+ <button id="stopBtn" disabled>Stop</button>
206
+ </div>
207
+ </div>
208
+ </div>
209
+
210
+ <script>
211
+ // Canvas und Audio Kontext Setup
212
+ const canvas = document.getElementById('visualizer');
213
+ const ctx = canvas.getContext('2d');
214
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
215
+
216
+ // DOM Elemente
217
+ const audioFileInput = document.getElementById('audioFile');
218
+ const playBtn = document.getElementById('playBtn');
219
+ const pauseBtn = document.getElementById('pauseBtn');
220
+ const stopBtn = document.getElementById('stopBtn');
221
+ const sensitivitySlider = document.getElementById('sensitivity');
222
+ const smoothnessSlider = document.getElementById('smoothness');
223
+ const fileStatus = document.getElementById('fileStatus');
224
+
225
+ // Variablen
226
+ let audioSource;
227
+ let analyser;
228
+ let dataArray;
229
+ let bufferLength;
230
+ let animationId;
231
+ let isPlaying = false;
232
+ let audioBuffer;
233
+ let rotationX = 0;
234
+ let rotationY = 0;
235
+
236
+ // Canvas Größe anpassen
237
+ function resizeCanvas() {
238
+ canvas.width = window.innerWidth;
239
+ canvas.height = window.innerHeight;
240
+ }
241
+
242
+ window.addEventListener('resize', resizeCanvas);
243
+ resizeCanvas();
244
+
245
+ // Audio File Handling
246
+ audioFileInput.addEventListener('change', function(e) {
247
+ const file = e.target.files[0];
248
+ if (!file) return;
249
+
250
+ fileStatus.textContent = `Geladen: ${file.name}`;
251
+
252
+ const reader = new FileReader();
253
+ reader.onload = function(e) {
254
+ const arrayBuffer = e.target.result;
255
+ audioContext.decodeAudioData(arrayBuffer, function(buffer) {
256
+ audioBuffer = buffer;
257
+ setupAudioAnalysis();
258
+ playBtn.disabled = false;
259
+ }, function(e) {
260
+ console.error('Error decoding audio data', e);
261
+ fileStatus.textContent = 'Fehler beim Laden der Audio-Datei';
262
+ });
263
+ };
264
+ reader.readAsArrayBuffer(file);
265
+ });
266
+
267
+ // Audio Analyse Setup
268
+ function setupAudioAnalysis() {
269
+ if (analyser) {
270
+ analyser.disconnect();
271
+ }
272
+
273
+ analyser = audioContext.createAnalyser();
274
+ analyser.fftSize = 256;
275
+ bufferLength = analyser.frequencyBinCount;
276
+ dataArray = new Uint8Array(bufferLength);
277
+
278
+ // Smoothing-Faktor basierend auf Slider
279
+ analyser.smoothingTimeConstant = (11 - smoothnessSlider.value) / 10;
280
+ }
281
+
282
+ // Ferrofluid Visualisierung
283
+ function visualize() {
284
+ if (!isPlaying || !analyser) return;
285
+
286
+ analyser.getByteFrequencyData(dataArray);
287
+
288
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
289
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
290
+
291
+ const centerX = canvas.width / 2;
292
+ const centerY = canvas.height / 2;
293
+ const baseRadius = Math.min(canvas.width, canvas.height) / 4;
294
+ const sensitivity = sensitivitySlider.value / 2;
295
+
296
+ ctx.save();
297
+ ctx.translate(centerX, centerY);
298
+
299
+ // 3D-Rotation basierend auf Audio-Daten
300
+ rotationX += dataArray[10] / 1000;
301
+ rotationY += dataArray[20] / 800;
302
+
303
+ ctx.rotateX(rotationX);
304
+ ctx.rotateY(rotationY);
305
+
306
+ // Ferrofluid-ähnliche Blob-Form zeichnen
307
+ ctx.beginPath();
308
+
309
+ for (let i = 0; i < bufferLength; i++) {
310
+ const amplitude = dataArray[i] / 255;
311
+ const angle = (i / bufferLength) * Math.PI * 2;
312
+ const radius = baseRadius + (amplitude * baseRadius * sensitivity);
313
+
314
+ const x = Math.cos(angle) * radius;
315
+ const y = Math.sin(angle) * radius;
316
+
317
+ // Z-Koordinate für 3D-Effekt
318
+ const z = Math.sin(angle * 2) * amplitude * 50;
319
+
320
+ if (i === 0) {
321
+ ctx.moveTo(x, y + z);
322
+ } else {
323
+ ctx.lineTo(x, y + z);
324
+ }
325
+ }
326
+
327
+ ctx.closePath();
328
+
329
+ // Ferrofluid-ähnlicher Gradient
330
+ const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, baseRadius * 2);
331
+ gradient.addColorStop(0, 'rgba(0, 255, 136, 0.8)');
332
+ gradient.addColorStop(0.5, 'rgba(0, 200, 100, 0.6)');
333
+ gradient.addColorStop(1, 'rgba(0, 100, 50, 0.4)');
334
+
335
+ ctx.fillStyle = gradient;
336
+ ctx.fill();
337
+
338
+ // Glänzende Highlights
339
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
340
+ ctx.lineWidth = 2;
341
+ ctx.stroke();
342
+
343
+ ctx.restore();
344
+
345
+ animationId = requestAnimationFrame(visualize);
346
+ }
347
+
348
+ // Steuerung
349
+ playBtn.addEventListener('click', function() {
350
+ if (!audioBuffer) return;
351
+
352
+ if (audioContext.state === 'suspended') {
353
+ audioContext.resume();
354
+ }
355
+
356
+ if (audioSource) {
357
+ audioSource.stop();
358
+ }
359
+
360
+ audioSource = audioContext.createBufferSource();
361
+ audioSource.buffer = audioBuffer;
362
+ audioSource.connect(analyser);
363
+ analyser.connect(audioContext.destination);
364
+
365
+ audioSource.start(0);
366
+ isPlaying = true;
367
+
368
+ playBtn.disabled = true;
369
+ pauseBtn.disabled = false;
370
+ stopBtn.disabled = false;
371
+
372
+ visualize();
373
+ });
374
+
375
+ pauseBtn.addEventListener('click', function() {
376
+ if (audioContext.state === 'running') {
377
+ audioContext.suspend().then(function() {
378
+ isPlaying = false;
379
+ playBtn.disabled = false;
380
+ pauseBtn.disabled = true;
381
+ cancelAnimationFrame(animationId);
382
+ });
383
+ }
384
+ });
385
+
386
+ stopBtn.addEventListener('click', function() {
387
+ if (audioSource) {
388
+ audioSource.stop();
389
+ audioSource = null;
390
+ }
391
+
392
+ isPlaying = false;
393
+ playBtn.disabled = false;
394
+ pauseBtn.disabled = true;
395
+ stopBtn.disabled = true;
396
+
397
+ cancelAnimationFrame(animationId);
398
+
399
+ // Canvas zurücksetzen
400
+ ctx.fillStyle = 'black';
401
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
402
+ });
403
+
404
+ // Slider-Event-Listener
405
+ smoothnessSlider.addEventListener('input', function() {
406
+ if (analyser) {
407
+ analyser.smoothingTimeConstant = (11 - this.value) / 10;
408
+ }
409
+ });
410
+
411
+ // Maus-Interaktion für zusätzliche Rotation
412
+ let mouseX = 0;
413
+ let mouseY = 0;
414
+
415
+ canvas.addEventListener('mousemove', function(e) {
416
+ if (!isPlaying) return;
417
+
418
+ mouseX = (e.clientX / canvas.width - 0.5) * 2;
419
+ mouseY = (e.clientY / canvas.height - 0.5) * 2;
420
+ });
421
+
422
+ // Touch-Interaktion für Mobile
423
+ canvas.addEventListener('touchmove', function(e) {
424
+ if (!isPlaying) return;
425
+ e.preventDefault();
426
+
427
+ const touch = e.touches[0];
428
+ mouseX = (touch.clientX / canvas.width - 0.5) * 2;
429
+ mouseY = (touch.clientY / canvas.height - 0.5) * 2;
430
+ }, { passive: false });
431
+
432
+ // Initialen schwarzen Hintergrund zeichnen
433
+ ctx.fillStyle = 'black';
434
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
435
+ </script>
436
+ </body>
437
+ </html>