kolaslab commited on
Commit
f0cde8c
·
verified ·
1 Parent(s): aa2e128

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +372 -19
index.html CHANGED
@@ -1,19 +1,372 @@
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="ru">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Audio Visualizer</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ background: #0f0f1a;
16
+ color: #fff;
17
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
18
+ overflow-x: hidden;
19
+ }
20
+
21
+ .container {
22
+ width: 100%;
23
+ min-height: 100vh;
24
+ padding: 20px;
25
+ position: relative;
26
+ }
27
+
28
+ header {
29
+ text-align: center;
30
+ padding: 40px 0;
31
+ animation: fadeIn 1s ease-in;
32
+ }
33
+
34
+ h1 {
35
+ font-size: 3em;
36
+ margin-bottom: 20px;
37
+ background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
38
+ -webkit-background-clip: text;
39
+ -webkit-text-fill-color: transparent;
40
+ }
41
+
42
+ .visualizer-container {
43
+ width: 100%;
44
+ height: calc(100vh - 200px);
45
+ margin: 0 auto;
46
+ background: rgba(255, 255, 255, 0.05);
47
+ border-radius: 15px;
48
+ padding: 20px;
49
+ position: relative;
50
+ }
51
+
52
+ canvas {
53
+ width: 100%;
54
+ height: 100%;
55
+ border-radius: 10px;
56
+ background: rgba(0, 0, 0, 0.3);
57
+ }
58
+
59
+ .controls {
60
+ position: fixed;
61
+ bottom: 20px;
62
+ left: 50%;
63
+ transform: translateX(-50%);
64
+ display: flex;
65
+ gap: 10px;
66
+ flex-wrap: wrap;
67
+ justify-content: center;
68
+ z-index: 100;
69
+ }
70
+
71
+ button {
72
+ padding: 10px 20px;
73
+ border: none;
74
+ border-radius: 25px;
75
+ background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
76
+ color: white;
77
+ cursor: pointer;
78
+ transition: transform 0.2s;
79
+ }
80
+
81
+ button:hover {
82
+ transform: scale(1.05);
83
+ }
84
+
85
+ input[type="file"] {
86
+ display: none;
87
+ }
88
+
89
+ .visualization-styles {
90
+ position: fixed;
91
+ top: 20px;
92
+ right: 20px;
93
+ display: flex;
94
+ gap: 10px;
95
+ flex-direction: column;
96
+ z-index: 100;
97
+ }
98
+
99
+ .style-option {
100
+ padding: 8px 15px;
101
+ border-radius: 15px;
102
+ background: rgba(255, 255, 255, 0.1);
103
+ cursor: pointer;
104
+ transition: background 0.3s;
105
+ }
106
+
107
+ .style-option:hover {
108
+ background: rgba(255, 255, 255, 0.2);
109
+ }
110
+
111
+ .center-image {
112
+ position: absolute;
113
+ top: 50%;
114
+ left: 50%;
115
+ transform: translate(-50%, -50%);
116
+ max-width: 200px;
117
+ max-height: 200px;
118
+ z-index: 10;
119
+ }
120
+
121
+ .background-image {
122
+ position: absolute;
123
+ top: 0;
124
+ left: 0;
125
+ width: 100%;
126
+ height: 100%;
127
+ object-fit: cover;
128
+ opacity: 0.3;
129
+ z-index: 1;
130
+ }
131
+
132
+ .fullscreen-btn {
133
+ position: fixed;
134
+ top: 20px;
135
+ left: 20px;
136
+ z-index: 100;
137
+ }
138
+
139
+ .credit {
140
+ position: fixed;
141
+ bottom: 10px;
142
+ right: 20px;
143
+ font-size: 14px;
144
+ opacity: 0.7;
145
+ z-index: 100;
146
+ }
147
+
148
+ @keyframes fadeIn {
149
+ from {
150
+ opacity: 0;
151
+ transform: translateY(-20px);
152
+ }
153
+ to {
154
+ opacity: 1;
155
+ transform: translateY(0);
156
+ }
157
+ }
158
+
159
+ @media (max-width: 768px) {
160
+ .visualizer-container {
161
+ padding: 10px;
162
+ }
163
+
164
+ h1 {
165
+ font-size: 2em;
166
+ }
167
+ }
168
+ </style>
169
+ </head>
170
+ <body>
171
+ <div class="container">
172
+ <header>
173
+ <h1>Audio Visualizer</h1>
174
+ </header>
175
+
176
+ <div class="visualizer-container" id="visualizer-container">
177
+ <canvas id="visualizer"></canvas>
178
+ <img id="centerImage" class="center-image" style="display: none;">
179
+ <img id="backgroundImage" class="background-image" style="display: none;">
180
+ </div>
181
+
182
+ <div class="controls">
183
+ <button onclick="document.getElementById('audioInput').click()">Upload Audio</button>
184
+ <button onclick="document.getElementById('imageInput').click()">Upload Center Image</button>
185
+ <button onclick="document.getElementById('bgImageInput').click()">Upload Background</button>
186
+ <button id="playPause">Play</button>
187
+ <input type="file" id="audioInput" accept="audio/*">
188
+ <input type="file" id="imageInput" accept="image/*,video/gif">
189
+ <input type="file" id="bgImageInput" accept="image/*,video/gif">
190
+ </div>
191
+
192
+ <button class="fullscreen-btn" onclick="toggleFullscreen()">Fullscreen</button>
193
+
194
+ <div class="visualization-styles">
195
+ <div class="style-option" data-style="bars">Bars</div>
196
+ <div class="style-option" data-style="wave">Wave</div>
197
+ <div class="style-option" data-style="circle">Circle</div>
198
+ </div>
199
+
200
+ <div class="credit">by Софронов Артемий</div>
201
+ </div>
202
+
203
+ <script>
204
+ let audioContext, analyser, source;
205
+ const canvas = document.getElementById('visualizer');
206
+ const ctx = canvas.getContext('2d');
207
+ let animationId;
208
+ let currentStyle = 'bars';
209
+ let centerImage = document.getElementById('centerImage');
210
+ let backgroundImage = document.getElementById('backgroundImage');
211
+ let bassValue = 0;
212
+
213
+ function resizeCanvas() {
214
+ canvas.width = canvas.clientWidth * window.devicePixelRatio;
215
+ canvas.height = canvas.clientHeight * window.devicePixelRatio;
216
+ }
217
+ resizeCanvas();
218
+ window.addEventListener('resize', resizeCanvas);
219
+
220
+ document.getElementById('audioInput').addEventListener('change', function(e) {
221
+ const file = e.target.files[0];
222
+ const audio = new Audio();
223
+ audio.src = URL.createObjectURL(file);
224
+ setupAudioContext(audio);
225
+ });
226
+
227
+ document.getElementById('imageInput').addEventListener('change', function(e) {
228
+ const file = e.target.files[0];
229
+ centerImage.src = URL.createObjectURL(file);
230
+ centerImage.style.display = 'block';
231
+ });
232
+
233
+ document.getElementById('bgImageInput').addEventListener('change', function(e) {
234
+ const file = e.target.files[0];
235
+ backgroundImage.src = URL.createObjectURL(file);
236
+ backgroundImage.style.display = 'block';
237
+ });
238
+
239
+ function setupAudioContext(audio) {
240
+ if (audioContext) audioContext.close();
241
+
242
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
243
+ analyser = audioContext.createAnalyser();
244
+ source = audioContext.createMediaElementSource(audio);
245
+
246
+ source.connect(analyser);
247
+ analyser.connect(audioContext.destination);
248
+
249
+ analyser.fftSize = 256;
250
+
251
+ audio.play();
252
+ draw();
253
+ }
254
+
255
+ function draw() {
256
+ const bufferLength = analyser.frequencyBinCount;
257
+ const dataArray = new Uint8Array(bufferLength);
258
+
259
+ function animate() {
260
+ animationId = requestAnimationFrame(animate);
261
+ analyser.getByteFrequencyData(dataArray);
262
+
263
+ ctx.fillStyle = 'rgba(15, 15, 26, 0.2)';
264
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
265
+
266
+ // Get bass value for image animation
267
+ bassValue = dataArray.slice(0, 10).reduce((a, b) => a + b) / 10;
268
+
269
+ if (centerImage.style.display !== 'none') {
270
+ const scale = 1 + (bassValue / 255) * 0.2;
271
+ centerImage.style.transform = `translate(-50%, -50%) scale(${scale})`;
272
+ }
273
+
274
+ switch(currentStyle) {
275
+ case 'bars':
276
+ drawBars(dataArray, bufferLength);
277
+ break;
278
+ case 'wave':
279
+ drawWave(dataArray, bufferLength);
280
+ break;
281
+ case 'circle':
282
+ drawCircle(dataArray, bufferLength);
283
+ break;
284
+ }
285
+ }
286
+
287
+ animate();
288
+ }
289
+
290
+ function drawBars(dataArray, bufferLength) {
291
+ const barWidth = canvas.width / bufferLength;
292
+
293
+ for(let i = 0; i < bufferLength; i++) {
294
+ const barHeight = dataArray[i] * canvas.height / 255;
295
+
296
+ const gradient = ctx.createLinearGradient(0, canvas.height, 0, 0);
297
+ gradient.addColorStop(0, '#ff6b6b');
298
+ gradient.addColorStop(1, '#4ecdc4');
299
+
300
+ ctx.fillStyle = gradient;
301
+ ctx.fillRect(i * barWidth, canvas.height - barHeight, barWidth - 1, barHeight);
302
+ }
303
+ }
304
+
305
+ function drawWave(dataArray, bufferLength) {
306
+ ctx.beginPath();
307
+ ctx.strokeStyle = '#4ecdc4';
308
+ ctx.lineWidth = 2;
309
+
310
+ for(let i = 0; i < bufferLength; i++) {
311
+ const x = i * (canvas.width / bufferLength);
312
+ const y = (dataArray[i] / 128.0) * (canvas.height / 2);
313
+
314
+ if(i === 0) {
315
+ ctx.moveTo(x, y);
316
+ } else {
317
+ ctx.lineTo(x, y);
318
+ }
319
+ }
320
+
321
+ ctx.stroke();
322
+ }
323
+
324
+ function drawCircle(dataArray, bufferLength) {
325
+ const centerX = canvas.width / 2;
326
+ const centerY = canvas.height / 2;
327
+ const radius = Math.min(centerX, centerY) - 50;
328
+
329
+ ctx.beginPath();
330
+ ctx.strokeStyle = '#ff6b6b';
331
+ ctx.lineWidth = 2;
332
+
333
+ for(let i = 0; i < bufferLength; i++) {
334
+ const angle = i * 2 * Math.PI / bufferLength;
335
+ const amplitude = (dataArray[i] * radius / 255) + radius;
336
+
337
+ const x = centerX + amplitude * Math.cos(angle);
338
+ const y = centerY + amplitude * Math.sin(angle);
339
+
340
+ if(i === 0) {
341
+ ctx.moveTo(x, y);
342
+ } else {
343
+ ctx.lineTo(x, y);
344
+ }
345
+ }
346
+
347
+ ctx.closePath();
348
+ ctx.stroke();
349
+
350
+ // Draw base circle
351
+ ctx.beginPath();
352
+ ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
353
+ ctx.strokeStyle = 'rgba(255, 107, 107, 0.3)';
354
+ ctx.stroke();
355
+ }
356
+
357
+ document.querySelectorAll('.style-option').forEach(option => {
358
+ option.addEventListener('click', function() {
359
+ currentStyle = this.dataset.style;
360
+ });
361
+ });
362
+
363
+ function toggleFullscreen() {
364
+ if (!document.fullscreenElement) {
365
+ document.documentElement.requestFullscreen();
366
+ } else {
367
+ document.exitFullscreen();
368
+ }
369
+ }
370
+ </script>
371
+ </body>
372
+ </html>