| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Audio Visualizer</title> |
| <style> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| body { |
| background: #111; |
| min-height: 100vh; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| font-family: 'Segoe UI', sans-serif; |
| } |
| |
| #visualizer-container { |
| position: relative; |
| width: 800px; |
| height: 400px; |
| background: rgba(255,255,255,0.05); |
| border-radius: 10px; |
| overflow: hidden; |
| margin-bottom: 20px; |
| } |
| |
| canvas { |
| position: absolute; |
| top: 0; |
| left: 0; |
| } |
| |
| .controls { |
| display: flex; |
| gap: 20px; |
| margin-bottom: 20px; |
| } |
| |
| button { |
| background: rgba(255,255,255,0.1); |
| border: none; |
| padding: 10px 20px; |
| color: white; |
| border-radius: 5px; |
| cursor: pointer; |
| transition: background 0.3s; |
| } |
| |
| button:hover { |
| background: rgba(255,255,255,0.2); |
| } |
| |
| .color-themes { |
| display: flex; |
| gap: 10px; |
| } |
| |
| .theme-btn { |
| width: 30px; |
| height: 30px; |
| border-radius: 50%; |
| cursor: pointer; |
| border: 2px solid transparent; |
| } |
| |
| .theme-btn:hover { |
| transform: scale(1.1); |
| } |
| |
| .theme-btn.active { |
| border-color: white; |
| } |
| |
| #file-input { |
| display: none; |
| } |
| |
| .upload-btn { |
| color: white; |
| padding: 10px 20px; |
| background: #2196f3; |
| border-radius: 5px; |
| cursor: pointer; |
| } |
| </style> |
| </head> |
| <body> |
| <div id="visualizer-container"> |
| <canvas id="canvas"></canvas> |
| </div> |
|
|
| <div class="controls"> |
| <button id="playPause">Play</button> |
| <label class="upload-btn"> |
| Upload Audio |
| <input type="file" id="file-input" accept="audio/*"> |
| </label> |
| </div> |
|
|
| <div class="color-themes"> |
| <div class="theme-btn active" style="background: linear-gradient(45deg, #ff6b6b, #ff8e8e)" data-colors='["#ff6b6b", "#ff8e8e"]'></div> |
| <div class="theme-btn" style="background: linear-gradient(45deg, #4facfe, #00f2fe)" data-colors='["#4facfe", "#00f2fe"]'></div> |
| <div class="theme-btn" style="background: linear-gradient(45deg, #43e97b, #38f9d7)" data-colors='["#43e97b", "#38f9d7"]'></div> |
| </div> |
|
|
| <script> |
| const canvas = document.getElementById('canvas'); |
| const ctx = canvas.getContext('2d'); |
| const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); |
| let analyser; |
| let source; |
| let audioElement; |
| let animation; |
| let currentColors = ["#ff6b6b", "#ff8e8e"]; |
| |
| function setupCanvas() { |
| canvas.width = canvas.offsetWidth; |
| canvas.height = canvas.offsetHeight; |
| } |
| |
| function setupAudio() { |
| audioElement = new Audio(); |
| source = audioCtx.createMediaElementSource(audioElement); |
| analyser = audioCtx.createAnalyser(); |
| analyser.fftSize = 256; |
| source.connect(analyser); |
| analyser.connect(audioCtx.destination); |
| } |
| |
| function draw() { |
| const bufferLength = analyser.frequencyBinCount; |
| const dataArray = new Uint8Array(bufferLength); |
| analyser.getByteFrequencyData(dataArray); |
| |
| ctx.clearRect(0, 0, canvas.width, canvas.height); |
| |
| const barWidth = canvas.width / bufferLength * 2.5; |
| const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height); |
| gradient.addColorStop(0, currentColors[0]); |
| gradient.addColorStop(1, currentColors[1]); |
| |
| ctx.fillStyle = gradient; |
| |
| for(let i = 0; i < bufferLength; i++) { |
| const barHeight = (dataArray[i] / 255) * canvas.height; |
| const x = i * barWidth; |
| const y = canvas.height - barHeight; |
| |
| ctx.beginPath(); |
| ctx.roundRect(x, y, barWidth - 2, barHeight, 5); |
| ctx.fill(); |
| } |
| |
| animation = requestAnimationFrame(draw); |
| } |
| |
| document.getElementById('file-input').addEventListener('change', function(e) { |
| const file = e.target.files[0]; |
| const url = URL.createObjectURL(file); |
| audioElement.src = url; |
| document.getElementById('playPause').textContent = 'Play'; |
| }); |
| |
| document.getElementById('playPause').addEventListener('click', function() { |
| if(audioCtx.state === 'suspended') { |
| audioCtx.resume(); |
| } |
| |
| if(audioElement.paused) { |
| audioElement.play(); |
| this.textContent = 'Pause'; |
| draw(); |
| } else { |
| audioElement.pause(); |
| this.textContent = 'Play'; |
| cancelAnimationFrame(animation); |
| } |
| }); |
| |
| document.querySelectorAll('.theme-btn').forEach(btn => { |
| btn.addEventListener('click', function() { |
| document.querySelector('.theme-btn.active').classList.remove('active'); |
| this.classList.add('active'); |
| currentColors = JSON.parse(this.dataset.colors); |
| }); |
| }); |
| |
| window.addEventListener('resize', setupCanvas); |
| |
| setupCanvas(); |
| setupAudio(); |
| </script> |
| </body> |
| </html> |