Music players have evolved significantly over the years, offering a variety of features and designs to enhance the listening experience. From sleek, minimalist interfaces to robust, feature-rich platforms, there's a music player for every preference.
In this article, we'll explore ten exemplary music players that stand out in the crowded market. Whether you're an audiophile or a casual listener, these options are sure to impress.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your music player projects with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect UI every time.
Loved by professionals, Subframe makes stunning design effortless. Start for free and transform your creative process today.
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect interfaces, including music players, in minutes. Its drag-and-drop editor ensures efficiency and precision.
Don't wait—start creating stunning UIs right away. Start for free and transform your design process today.
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spectra Player</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; user-select: none; } :root { --bg-color: #121212; --text-color: #f5f5f5; --accent-color: #0dffe1; --accent-glow: rgba(13, 255, 225, 0.2); --secondary-color: #252525; --muted-color: #888; --transition: all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1); } body { background-color: var(--bg-color); color: var(--text-color); height: 700px; width: 700px; max-width: 100%; max-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; padding: 20px; } .player-container { width: 90%; max-width: 400px; background: linear-gradient(145deg, #151515, #1a1a1a); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); border-radius: 20px; padding: 30px; position: relative; overflow: hidden; transition: transform 0.3s ease; } .player-container:hover { transform: translateY(-5px); } .player-container::before { content: ''; position: absolute; width: 150%; height: 120px; background: linear-gradient(90deg, transparent, var(--accent-glow), transparent); top: -50px; left: -25%; transform: rotate(5deg); animation: glow 8s linear infinite; opacity: 0.3; } @keyframes glow { 0% { transform: translateX(-100%) rotate(5deg); } 100% { transform: translateX(100%) rotate(5deg); } } .album-art { width: 100%; height: 0; padding-bottom: 100%; border-radius: 12px; overflow: hidden; position: relative; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); margin-bottom: 20px; background-size: cover; background-position: center; transition: var(--transition); } .album-art img { width: 100%; height: 100%; object-fit: cover; position: absolute; transition: var(--transition); } .album-art:hover img { transform: scale(1.05); } .track-info { text-align: left; margin-bottom: 25px; } .track-name { font-size: 24px; font-weight: 600; margin-bottom: 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .artist-name { font-size: 16px; color: var(--muted-color); margin-bottom: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .album-name { font-size: 14px; color: var(--muted-color); opacity: 0.8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .progress-container { width: 100%; height: 6px; background-color: var(--secondary-color); border-radius: 3px; position: relative; cursor: pointer; margin-bottom: 15px; overflow: hidden; } .progress-bar { height: 100%; width: 35%; background-color: var(--accent-color); border-radius: 3px; position: relative; box-shadow: 0 0 10px var(--accent-glow); transition: width 0.1s linear; } .progress-thumb { width: 12px; height: 12px; background-color: var(--accent-color); border-radius: 50%; position: absolute; top: 50%; right: 0; transform: translate(50%, -50%); box-shadow: 0 0 10px var(--accent-color); opacity: 0; transition: opacity 0.3s ease; } .progress-container:hover .progress-thumb { opacity: 1; } .time-info { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted-color); margin-bottom: 25px; } .controls { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; } .control-btn { border: none; background: none; cursor: pointer; color: var(--text-color); display: flex; align-items: center; justify-content: center; transition: var(--transition); outline: none; position: relative; } .control-btn:hover { color: var(--accent-color); transform: scale(1.1); } .control-btn:active { transform: scale(0.95); } .control-btn.play-pause { width: 60px; height: 60px; background-color: var(--secondary-color); border-radius: 50%; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); position: relative; z-index: 2; } .control-btn.play-pause:hover { background-color: var(--accent-color); color: var(--bg-color); box-shadow: 0 0 20px var(--accent-glow); } .control-btn.play-pause:active { transform: scale(0.95); } .control-btn svg { width: 24px; height: 24px; } .control-btn.play-pause svg { width: 30px; height: 30px; } .volume-container { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 5px; } .volume-icon { color: var(--muted-color); margin-right: 10px; transition: var(--transition); } .volume-icon:hover { color: var(--accent-color); } .volume-slider { -webkit-appearance: none; width: 100px; height: 4px; background-color: var(--secondary-color); border-radius: 2px; outline: none; transition: var(--transition); } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; background-color: var(--text-color); border-radius: 50%; cursor: pointer; transition: var(--transition); } .volume-slider:hover::-webkit-slider-thumb { background-color: var(--accent-color); box-shadow: 0 0 10px var(--accent-glow); } .additional-controls { display: flex; justify-content: space-between; align-items: center; } .control-small { color: var(--muted-color); font-size: 12px; transition: var(--transition); cursor: pointer; display: flex; align-items: center; gap: 5px; } .control-small:hover { color: var(--accent-color); } .control-small svg { width: 16px; height: 16px; } .mini-visualizer { display: flex; align-items: flex-end; justify-content: center; gap: 3px; height: 20px; margin-top: 15px; } .visualizer-bar { width: 3px; height: 5px; background-color: var(--accent-color); border-radius: 1px; animation: visualize 1.2s ease-in-out infinite; } .visualizer-bar:nth-child(1) { animation-delay: 0.2s; } .visualizer-bar:nth-child(2) { animation-delay: 0.5s; } .visualizer-bar:nth-child(3) { animation-delay: 0.1s; } .visualizer-bar:nth-child(4) { animation-delay: 0.8s; } .visualizer-bar:nth-child(5) { animation-delay: 0.3s; } .visualizer-bar:nth-child(6) { animation-delay: 0.6s; } .visualizer-bar:nth-child(7) { animation-delay: 0.9s; } .visualizer-bar:nth-child(8) { animation-delay: 0.4s; } .visualizer-bar:nth-child(9) { animation-delay: 0.7s; } .visualizer-bar:nth-child(10) { animation-delay: 0.2s; } @keyframes visualize { 0%, 100% { height: 3px; } 50% { height: 15px; } } .up-next { margin-top: 30px; width: 90%; max-width: 400px; transition: var(--transition); } .up-next-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .up-next-title { font-size: 16px; font-weight: 600; } .up-next-action { color: var(--accent-color); font-size: 14px; cursor: pointer; transition: var(--transition); } .up-next-action:hover { text-decoration: underline; } .queue-item { display: flex; align-items: center; padding: 10px 15px; background-color: rgba(37, 37, 37, 0.5); border-radius: 8px; margin-bottom: 10px; transition: var(--transition); cursor: pointer; } .queue-item:hover { background-color: var(--secondary-color); transform: translateX(5px); } .queue-item-art { width: 40px; height: 40px; border-radius: 6px; margin-right: 15px; overflow: hidden; } .queue-item-art img { width: 100%; height: 100%; object-fit: cover; } .queue-item-info { flex: 1; overflow: hidden; } .queue-item-title { font-size: 14px; margin-bottom: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .queue-item-artist { font-size: 12px; color: var(--muted-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .queue-item-duration { font-size: 12px; color: var(--muted-color); margin-left: 10px; } @media (max-width: 600px) { .player-container { width: 95%; padding: 20px; } .track-name { font-size: 20px; } .artist-name { font-size: 14px; } .album-name { font-size: 12px; } .control-btn.play-pause { width: 50px; height: 50px; } .control-btn.play-pause svg { width: 25px; height: 25px; } .up-next { width: 95%; } } /* Animation for track change */ @keyframes slideIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .slide-in { animation: slideIn 0.4s ease forwards; } /* Pulse animation for the play button */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 var(--accent-glow); } 70% { box-shadow: 0 0 0 10px rgba(13, 255, 225, 0); } 100% { box-shadow: 0 0 0 0 rgba(13, 255, 225, 0); } } .playing .control-btn.play-pause { animation: pulse 1.5s infinite; background-color: var(--accent-color); color: var(--bg-color); } </style> </head> <body> <div class="player-container" id="playerContainer"> <div class="album-art" id="albumArt"> <img src="https://images.unsplash.com/photo-1614613535308-eb5fbd3d2c17?q=80&w=2070&auto=format&fit=crop" alt="Album Art"> </div> <div class="track-info"> <div class="track-name" id="trackName">Midnight Echo</div> <div class="artist-name" id="artistName">Synthwave Collective</div> <div class="album-name" id="albumName">Neon Horizons · 2023</div> </div> <div class="progress-container" id="progressContainer"> <div class="progress-bar" id="progressBar"> <div class="progress-thumb"></div> </div> </div> <div class="time-info"> <div class="current-time" id="currentTime">1:45</div> <div class="total-time" id="totalTime">4:30</div> </div> <div class="controls"> <button class="control-btn" id="prevBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7" /> </svg> </button> <button class="control-btn" id="rewindBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12.066 11.2a1 1 0 000 1.6l5.334 4A1 1 0 0019 16V8a1 1 0 00-1.6-.8l-5.333 4zM4.066 11.2a1 1 0 000 1.6l5.334 4A1 1 0 0011 16V8a1 1 0 00-1.6-.8l-5.334 4z" /> </svg> </button> <button class="control-btn play-pause" id="playPauseBtn"> <svg id="playIcon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="display: none;"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg> <svg id="pauseIcon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg> </button> <button class="control-btn" id="forwardBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.933 12.8a1 1 0 000-1.6L6.6 7.2A1 1 0 005 8v8a1 1 0 001.6.8l5.333-4zM19.933 12.8a1 1 0 000-1.6l-5.333-4A1 1 0 0013 8v8a1 1 0 001.6.8l5.333-4z" /> </svg> </button> <button class="control-btn" id="nextBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7-7 7M5 5l7 7-7 7" /> </svg> </button> </div> <div class="volume-container"> <div class="volume-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" width="16" height="16"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" /> </svg> </div> <input type="range" min="0" max="100" value="80" class="volume-slider" id="volumeSlider"> </div> <div class="additional-controls"> <div class="control-small" id="shuffleBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" /> </svg> <span>Shuffle</span> </div> <div class="control-small" id="repeatBtn"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> </svg> <span>Repeat</span> </div> </div> <div class="mini-visualizer" id="visualizer"> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> </div> </div> <div class="up-next"> <div class="up-next-header"> <div class="up-next-title">Up Next</div> <div class="up-next-action" id="viewQueueBtn">View Queue</div> </div> <div class="queue-list"> <div class="queue-item" data-track="Digital Dreams" data-artist="Electro Sync" data-img="https://images.unsplash.com/photo-1633107386058-5ea5f1a162fc?q=80&w=2070&auto=format&fit=crop"> <div class="queue-item-art"> <img src="https://images.unsplash.com/photo-1633107386058-5ea5f1a162fc?q=80&w=2070&auto=format&fit=crop" alt="Digital Dreams"> </div> <div class="queue-item-info"> <div class="queue-item-title">Digital Dreams</div> <div class="queue-item-artist">Electro Sync</div> </div> <div class="queue-item-duration">3:45</div> </div> <div class="queue-item" data-track="Cyber Street" data-artist="Neon Pulse" data-img="https://images.unsplash.com/photo-1648505886471-3f98cf15fc00?q=80&w=1974&auto=format&fit=crop"> <div class="queue-item-art"> <img src="https://images.unsplash.com/photo-1648505886471-3f98cf15fc00?q=80&w=1974&auto=format&fit=crop" alt="Cyber Street"> </div> <div class="queue-item-info"> <div class="queue-item-title">Cyber Street</div> <div class="queue-item-artist">Neon Pulse</div> </div> <div class="queue-item-duration">4:12</div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Player elements const playerContainer = document.getElementById('playerContainer'); const playPauseBtn = document.getElementById('playPauseBtn'); const playIcon = document.getElementById('playIcon'); const pauseIcon = document.getElementById('pauseIcon'); const nextBtn = document.getElementById('nextBtn'); const prevBtn = document.getElementById('prevBtn'); const rewindBtn = document.getElementById('rewindBtn'); const forwardBtn = document.getElementById('forwardBtn'); const progressBar = document.getElementById('progressBar'); const progressContainer = document.getElementById('progressContainer'); const currentTimeElement = document.getElementById('currentTime'); const totalTimeElement = document.getElementById('totalTime'); const volumeSlider = document.getElementById('volumeSlider'); const shuffleBtn = document.getElementById('shuffleBtn'); const repeatBtn = document.getElementById('repeatBtn'); const visualizer = document.getElementById('visualizer'); const viewQueueBtn = document.getElementById('viewQueueBtn'); const trackName = document.getElementById('trackName'); const artistName = document.getElementById('artistName'); const albumName = document.getElementById('albumName'); const albumArt = document.getElementById('albumArt'); const queueItems = document.querySelectorAll('.queue-item'); // Player state let isPlaying = true; let isShuffle = false; let isRepeat = false; let progressInterval; let progressPercent = 35; // Initialize the player function initPlayer() { // Update play button state updatePlayPauseState(); // Set up the progress update simulation startProgressSimulation(); // Add event listeners playPauseBtn.addEventListener('click', togglePlayPause); nextBtn.addEventListener('click', nextTrack); prevBtn.addEventListener('click', prevTrack); rewindBtn.addEventListener('click', rewindTrack); forwardBtn.addEventListener('click', forwardTrack); progressContainer.addEventListener('click', seekTrack); volumeSlider.addEventListener('input', updateVolume); shuffleBtn.addEventListener('click', toggleShuffle); repeatBtn.addEventListener('click', toggleRepeat); viewQueueBtn.addEventListener('click', viewQueue); // Set up queue items click events queueItems.forEach(item => { item.addEventListener('click', () => changeTrack(item)); }); } // Toggle play/pause state function togglePlayPause() { isPlaying = !isPlaying; updatePlayPauseState(); if (isPlaying) { playerContainer.classList.add('playing'); startProgressSimulation(); } else { playerContainer.classList.remove('playing'); clearInterval(progressInterval); } } // Update play/pause button state function updatePlayPauseState() { if (isPlaying) { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; visualizer.style.display = 'flex'; } else { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; visualizer.style.display = 'none'; } } // Start progress bar simulation function startProgressSimulation() { clearInterval(progressInterval); progressInterval = setInterval(() => { progressPercent += 0.1; if (progressPercent >= 100) { if (isRepeat) { progressPercent = 0; } else { nextTrack(); return; } } updateProgress(); }, 100); } // Update progress bar function updateProgress() { progressBar.style.width = `${progressPercent}%`; // Update time display (simulation) const currentSeconds = Math.floor(4.5 * progressPercent / 100 * 60); const minutes = Math.floor(currentSeconds / 60); const seconds = currentSeconds % 60; currentTimeElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; } // Seek track on progress bar click function seekTrack(e) { const containerWidth = progressContainer.clientWidth; const clickPosition = e.clientX - progressContainer.getBoundingClientRect().left; progressPercent = (clickPosition / containerWidth) * 100; updateProgress(); } // Play next track function nextTrack() { animateTrackChange(); setTimeout(() => { // Get a random queue item for demonstration const items = Array.from(queueItems); const randomItem = items[Math.floor(Math.random() * items.length)]; changeTrack(randomItem); // Reset progress progressPercent = 0; updateProgress(); }, 300); } // Play previous track function prevTrack() { animateTrackChange(); setTimeout(() => { // Just use the first queue item for demonstration changeTrack(queueItems[0]); // Reset progress progressPercent = 0; updateProgress(); }, 300); } // Rewind track by 10 seconds function rewindTrack() { progressPercent = Math.max(0, progressPercent - 10); updateProgress(); } // Forward track by 10 seconds function forwardTrack() { progressPercent = Math.min(100, progressPercent + 10); updateProgress(); } // Update volume function updateVolume() { // Visual feedback only if (volumeSlider.value < 20) { volumeSlider.style.accentColor = '#555'; } else { volumeSlider.style.accentColor = 'var(--accent-color)'; } } // Toggle shuffle function toggleShuffle() { isShuffle = !isShuffle; if (isShuffle) { shuffleBtn.style.color = 'var(--accent-color)'; } else { shuffleBtn.style.color = 'var(--muted-color)'; } } // Toggle repeat function toggleRepeat() { isRepeat = !isRepeat; if (isRepeat) { repeatBtn.style.color = 'var(--accent-color)'; } else { repeatBtn.style.color = 'var(--muted-color)'; } } // View queue (just a visual effect for the demo) function viewQueue() { const queueList = document.querySelector('.queue-list'); queueList.classList.add('slide-in'); setTimeout(() => { queueList.classList.remove('slide-in'); }, 500); } // Change track based on queue item function changeTrack(item) { const track = item.getAttribute('data-track'); const artist = item.getAttribute('data-artist'); const img = item.getAttribute('data-img'); trackName.textContent = track; artistName.textContent = artist; albumName.textContent = `Neon Horizons · 2023`; albumArt.querySelector('img').src = img; // Ensure player is playing if (!isPlaying) { togglePlayPause(); } else { // Reset progress progressPercent = 0; updateProgress(); } // Add animation trackName.classList.add('slide-in'); artistName.classList.add('slide-in'); albumName.classList.add('slide-in'); setTimeout(() => { trackName.classList.remove('slide-in'); artistName.classList.remove('slide-in'); albumName.classList.remove('slide-in'); }, 500); } // Animate track change function animateTrackChange() { trackName.style.opacity = 0; artistName.style.opacity = 0; albumName.style.opacity = 0; albumArt.style.opacity = 0.5; setTimeout(() => { trackName.style.opacity = 1; artistName.style.opacity = 1; albumName.style.opacity = 1; albumArt.style.opacity = 1; }, 300); } // Initialize initPlayer(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>RetroTunes Player</title> <style> @import url('https://fonts.googleapis.com/css2?family=Monoton&family=Permanent+Marker&family=Rubik:wght@400;500;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary-color: #f5d5cb; --secondary-color: #94b9af; --accent-color: #e2725b; --dark-color: #2d3047; --light-color: #f7f3e9; --wood-texture: repeating-linear-gradient(45deg, #d7b29d 0px, #d7b29d 2px, #c9a38b 2px, #c9a38b 4px); } body { font-family: 'Rubik', sans-serif; background-color: var(--light-color); color: var(--dark-color); width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; } .player-container { width: 100%; max-width: 650px; height: 650px; background: var(--wood-texture); border-radius: 10px; box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2); overflow: hidden; position: relative; display: flex; flex-direction: column; padding: 20px; } .noise-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAABGJJREFUaEPtmcuOHUUMhr/yMCDBgpfgDSDBC7BgAStgBbwDS3gB2LIChBASEleJm7iIm8BFhIBAghCXF2DNzPTMdLtcLpf7dPcJIxGJPqnPVfVXVf/lctm8QMNsXiAcLEA2vZMXO3KxIxtk4OJabXStZrPZ04GXgZeAC+HvC8A54I/w9x/gz8PDw11Jssx3YkB2dnZerap3gHeB54HWdxZA/gS+r6rPjo6OvmoJZlIgu7u7t1XV+8B7wLUW0D05Z4DPq+rjg4ODX3vyT9LJgezv779SVR8Ct09C6E5yUlUfHR4efjclnkmA7O3tXa2qT4B3piQ/knupqj7c399/9erVq/+N5I6mTwKkqqbcidaxb6vq7ePj4583AZYgVTXVTpwTPQHfqKq7BwcHv7UAW8v+BsjOzs5nwDtrJW4u/Lqq3jo6OvrJSV+c5wAJdvZzC/Yj18L3wPXgzBT48vDw8AM32CggwbZ+AC65iTtz/gG8HviVvQW+B26E3/8Hvjw8PLzrBDMKSFVNfTA7bPSbqro/gtkKsM5U1SfOh9MKZLKdqKoHIV79Erj5PYzMArMRKIE5cYJZCaSqxjiOoZXgLzHxnkK2BkrwP6dVWoC46tXDEETnkA8xjvWO1FVVd1xWayWQ3d3dL6rqrRb0K2TOQjw6CYmkqVtV9f7R0dGHK/PWLrMSSMg63uiB0pKzCsAqmRDATbjWhQ9PAem6d9j+JiJeR36Zk1VgGNcKSNU6j9lkRhW+dM285gPi7aX43mXxIvlUO7zKIiPnyEPglfPIzXLqJmJVhkLwn0c2S9VkLJBHY4CsAlW1sETW2udhVb01NyMqm8i8f6sW72WsMNVKm0aSGS+SbRvW51I1GbsjD5YoEu5VVT0L6fdNK+lXgBJMZhSYUOlfj23AWoGE3Ujdq1Yg2f5SNYnWZlQPIxvMsNgwrQUSssVfgSfnWkZUeNWOZLK5grgbdtJ/3Uq+aitCr9ILqPlurAUj2dqtlXP77RCUe/Yiyo59SVZgRGbC9Xomdj1vBRKsxi9jQdgOTbGDi7IRmKrStTrvNXfrjqzciYzQ0irkz4OsRNK9OvchaNnPVwIJVfQjd9OfZcXzXGCifbWq3h3aKLYA+Ri45y54FfNzgQmZ3M2xB1ILEPS3M/JLM5jQpXrlj4+Pn7RcpCUg2Q9qJJIJzKoGcFl+KxDP6SpZSiYwnqZ19HmUBcje3t5bVfXlWPWV+anTZ9qFnuqcDcTDZfKtO4IM+GIZnYWsTG12M4O67o0CMjT3c08OGmHMKNH00A1kdAdXAVooJKkfqW0mj1TGZbJjgSj/FHDdTvU68Zf62wbEwfhUHNZydNsOJH8JHnw2t9YU/ZP5aKbtjqTeZXqVWvZV5a/t2nQdJL/n3uVugwBNUX9tXLsCAo2PHJtcq7kvyQXYdcSdYhcgUzA5hnOxI2NY2+TcxY5swuoY7sWOjGFtk3MXO7IJq2O4/wN7qoNVMp2I7QAAAABJRU5ErkJggg=='); opacity: 0.05; pointer-events: none; z-index: 5; } .player-title { text-align: center; margin-bottom: 10px; position: relative; z-index: 2; } .player-title h1 { font-family: 'Monoton', cursive; color: var(--accent-color); font-size: 2.2rem; text-shadow: 3px 3px 0 var(--dark-color); margin-bottom: 5px; letter-spacing: 2px; } .player-title p { font-family: 'Permanent Marker', cursive; font-size: 0.9rem; color: var(--dark-color); opacity: 0.8; } .record-player { flex: 1; display: flex; flex-direction: column; position: relative; background-color: var(--primary-color); border-radius: 10px; padding: 20px; box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.2); overflow: hidden; z-index: 1; } .record-container { flex: 1; display: flex; justify-content: center; align-items: center; position: relative; } .vinyl-record { width: 250px; height: 250px; background: radial-gradient(circle, #111 0%, #333 50%, #111 100%); border-radius: 50%; position: relative; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; transition: transform 0.5s ease; will-change: transform; } .vinyl-record.playing { animation: spin 3s linear infinite; } .vinyl-record::before { content: ''; position: absolute; width: 30%; height: 30%; background: radial-gradient(circle, #ddd 0%, #bbb 40%, #999 100%); border-radius: 50%; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); } .vinyl-record::after { content: ''; position: absolute; width: 5%; height: 5%; background: #333; border-radius: 50%; box-shadow: 0 0 5px rgba(0, 0, 0, 0.5); } .grooves { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; overflow: hidden; opacity: 0.2; pointer-events: none; } .grooves::before { content: ''; position: absolute; top: 15%; left: 15%; right: 15%; bottom: 15%; border: 1px solid #666; border-radius: 50%; box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.05), 0 0 0 20px rgba(255, 255, 255, 0.05), 0 0 0 30px rgba(255, 255, 255, 0.05), 0 0 0 40px rgba(255, 255, 255, 0.05), 0 0 0 50px rgba(255, 255, 255, 0.05), 0 0 0 60px rgba(255, 255, 255, 0.05); } .tonearm { position: absolute; width: 150px; height: 30px; background: linear-gradient(to right, #333, #555); top: 40%; right: 5%; border-radius: 5px; transform-origin: right center; transform: rotate(-30deg); transition: transform 0.5s ease; z-index: 2; } .tonearm.playing { transform: rotate(0deg); } .tonearm::before { content: ''; position: absolute; width: 20px; height: 20px; background: #777; border-radius: 50%; right: -10px; top: 5px; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); } .tonearm::after { content: ''; position: absolute; width: 10px; height: 10px; background: #ddd; border-radius: 50%; left: 5px; top: 10px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); } .cassette { width: 200px; height: 120px; background: var(--secondary-color); border-radius: 8px; position: relative; margin: 0 auto; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); overflow: hidden; z-index: 1; } .cassette::before { content: ''; position: absolute; top: 20px; left: 20px; right: 20px; bottom: 20px; background: rgba(0, 0, 0, 0.2); border-radius: 4px; } .reel { position: absolute; width: 40px; height: 40px; border-radius: 50%; background: #333; top: 40px; } .reel::before { content: ''; position: absolute; width: 10px; height: 10px; background: #999; border-radius: 50%; top: 15px; left: 15px; } .reel.left { left: 40px; } .reel.right { right: 40px; } .cassette-label { position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); font-family: 'Permanent Marker', cursive; font-size: 0.7rem; color: var(--dark-color); white-space: nowrap; } .tape { position: absolute; height: 2px; background: #333; top: 60px; left: 58px; right: 58px; } .controls { padding: 20px 10px; display: flex; flex-direction: column; background-color: var(--dark-color); border-radius: 10px; margin-top: 20px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 2; } .track-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; color: var(--light-color); font-family: 'Rubik', sans-serif; } .track-title { flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: 700; font-size: 1.1rem; } .track-artist { flex: 1; text-align: right; font-size: 0.9rem; font-style: italic; opacity: 0.8; } .progress-container { height: 10px; background-color: rgba(255, 255, 255, 0.1); border-radius: 5px; margin-bottom: 15px; overflow: hidden; position: relative; } .progress-bar { height: 100%; background-color: var(--accent-color); width: 0; border-radius: 5px; transition: width 0.3s linear; } .time-display { display: flex; justify-content: space-between; color: var(--light-color); font-size: 0.8rem; margin-bottom: 15px; } .buttons { display: flex; justify-content: space-between; align-items: center; } .control-button { background: none; border: none; color: var(--light-color); font-size: 1.5rem; cursor: pointer; width: 40px; height: 40px; display: flex; justify-content: center; align-items: center; transition: transform 0.2s, color 0.2s; border-radius: 50%; } .control-button:hover { color: var(--accent-color); transform: scale(1.1); } .control-button.play-pause { background-color: var(--accent-color); color: var(--dark-color); width: 50px; height: 50px; font-size: 1.8rem; } .control-button.play-pause:hover { transform: scale(1.1); color: var(--dark-color); box-shadow: 0 0 15px var(--accent-color); } .volume-container { display: flex; align-items: center; position: relative; } .volume-knob { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, #999, #555); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); position: relative; cursor: pointer; transform: rotate(0deg); transition: transform 0.2s; } .volume-knob:hover { transform: scale(1.1); } .volume-knob::before { content: ''; position: absolute; width: 2px; height: 15px; background: var(--light-color); top: 5px; left: 50%; transform: translateX(-50%); border-radius: 2px; } .playlist { margin-top: 15px; position: relative; z-index: 2; } .playlist-label { font-family: 'Permanent Marker', cursive; color: var(--accent-color); font-size: 1rem; margin-bottom: 5px; text-transform: uppercase; letter-spacing: 1px; } .playlist-tracks { display: flex; overflow-x: auto; gap: 10px; scrollbar-width: thin; scrollbar-color: var(--accent-color) var(--primary-color); padding-bottom: 5px; } .playlist-tracks::-webkit-scrollbar { height: 5px; } .playlist-tracks::-webkit-scrollbar-track { background: var(--primary-color); border-radius: 10px; } .playlist-tracks::-webkit-scrollbar-thumb { background-color: var(--accent-color); border-radius: 10px; } .track-item { min-width: 100px; padding: 5px 10px; background-color: rgba(0, 0, 0, 0.1); border-radius: 5px; cursor: pointer; transition: background-color 0.2s, transform 0.2s; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; text-align: center; font-size: 0.8rem; } .track-item:hover { background-color: var(--accent-color); color: var(--light-color); transform: translateY(-2px); } .track-item.active { background-color: var(--accent-color); color: var(--light-color); font-weight: bold; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .equalizer { display: flex; justify-content: center; align-items: flex-end; height: 20px; gap: 2px; margin-top: 5px; } .equalizer-bar { width: 3px; background-color: var(--light-color); border-radius: 1.5px; opacity: 0.7; } @media (max-width: 700px) { .player-container { padding: 15px; height: auto; } .player-title h1 { font-size: 1.8rem; } .vinyl-record { width: 180px; height: 180px; } .track-info { flex-direction: column; align-items: flex-start; gap: 5px; } .track-title, .track-artist { text-align: left; } .control-button { font-size: 1.2rem; width: 30px; height: 30px; } .control-button.play-pause { width: 40px; height: 40px; font-size: 1.5rem; } .tonearm { width: 100px; right: 10%; } .cassette { width: 160px; height: 100px; } .reel { width: 30px; height: 30px; top: 35px; } .reel.left { left: 30px; } .reel.right { right: 30px; } .tape { top: 50px; left: 45px; right: 45px; } .controls { padding: 15px 10px; } } </style> </head> <body> <div class="player-container"> <div class="noise-overlay"></div> <div class="player-title"> <h1>RetroTunes</h1> <p>Analog Sound in a Digital World</p> </div> <div class="record-player"> <div class="record-container"> <div class="vinyl-record"> <div class="grooves"></div> </div> <div class="tonearm"></div> <div class="cassette"> <div class="reel left"></div> <div class="reel right"></div> <div class="tape"></div> <div class="cassette-label">MIXTAPE '86</div> </div> </div> <div class="controls"> <div class="track-info"> <div class="track-title">Vinyl Dreams</div> <div class="track-artist">The Analog Lovers</div> </div> <div class="progress-container"> <div class="progress-bar"></div> </div> <div class="time-display"> <div class="current-time">0:00</div> <div class="total-time">3:45</div> </div> <div class="buttons"> <button class="control-button skip-back"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19 20L9 12L19 4V20Z" fill="currentColor"/> <rect x="7" y="4" width="2" height="16" fill="currentColor"/> </svg> </button> <button class="control-button rewind"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M11 17.9L4.1 12L11 6.1V17.9Z" fill="currentColor"/> <path d="M20 17.9L13.1 12L20 6.1V17.9Z" fill="currentColor"/> </svg> </button> <button class="control-button play-pause"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="play-icon"> <path d="M8 5V19L19 12L8 5Z" fill="currentColor"/> </svg> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="pause-icon" style="display: none;"> <rect x="6" y="4" width="4" height="16" fill="currentColor"/> <rect x="14" y="4" width="4" height="16" fill="currentColor"/> </svg> </button> <button class="control-button fast-forward"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M13 6.1L19.9 12L13 17.9V6.1Z" fill="currentColor"/> <path d="M4 6.1L10.9 12L4 17.9V6.1Z" fill="currentColor"/> </svg> </button> <button class="control-button skip-forward"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 4L15 12L5 20V4Z" fill="currentColor"/> <rect x="15" y="4" width="2" height="16" fill="currentColor"/> </svg> </button> </div> <div class="equalizer"> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> <div class="equalizer-bar"></div> </div> </div> </div> <div class="playlist"> <div class="playlist-label">Side A</div> <div class="playlist-tracks"> <div class="track-item active">Vinyl Dreams</div> <div class="track-item">Cassette Waves</div> <div class="track-item">Turntable Blues</div> <div class="track-item">Analog Sunrise</div> <div class="track-item">Magnetic Beats</div> <div class="track-item">Hiss & Crackle</div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const playPauseBtn = document.querySelector('.play-pause'); const playIcon = document.querySelector('.play-icon'); const pauseIcon = document.querySelector('.pause-icon'); const vinylRecord = document.querySelector('.vinyl-record'); const tonearm = document.querySelector('.tonearm'); const progressBar = document.querySelector('.progress-bar'); const currentTimeDisplay = document.querySelector('.current-time'); const trackItems = document.querySelectorAll('.track-item'); const trackTitle = document.querySelector('.track-title'); const trackArtist = document.querySelector('.track-artist'); const equalizerBars = document.querySelectorAll('.equalizer-bar'); let isPlaying = false; let progressInterval; let currentProgress = 0; const totalDuration = 225; // 3:45 in seconds const trackData = [ { title: "Vinyl Dreams", artist: "The Analog Lovers", duration: "3:45" }, { title: "Cassette Waves", artist: "Magnetic Tape", duration: "4:12" }, { title: "Turntable Blues", artist: "DJ Retrograde", duration: "3:22" }, { title: "Analog Sunrise", artist: "Morning Groove Collective", duration: "5:07" }, { title: "Magnetic Beats", artist: "Hi-Fi Lounge", duration: "3:56" }, { title: "Hiss & Crackle", artist: "Vintage Soundsystem", duration: "4:30" } ]; function formatTime(seconds) { const minutes = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${minutes}:${secs.toString().padStart(2, '0')}`; } function updateProgress() { currentProgress += 0.1; if (currentProgress > totalDuration) { currentProgress = 0; nextTrack(); return; } const progressPercent = (currentProgress / totalDuration) * 100; progressBar.style.width = `${progressPercent}%`; currentTimeDisplay.textContent = formatTime(currentProgress); // Animate the left reel to appear to be emptying and the right reel filling const leftReel = document.querySelector('.reel.left'); const rightReel = document.querySelector('.reel.right'); const reelProgress = currentProgress / totalDuration; leftReel.style.boxShadow = `inset ${-10 + reelProgress * 20}px 0 10px rgba(0, 0, 0, 0.3)`; rightReel.style.boxShadow = `inset ${10 - reelProgress * 20}px 0 10px rgba(0, 0, 0, 0.3)`; } function togglePlay() { isPlaying = !isPlaying; if (isPlaying) { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; vinylRecord.classList.add('playing'); tonearm.classList.add('playing'); progressInterval = setInterval(updateProgress, 100); animateEqualizer(); } else { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; vinylRecord.classList.remove('playing'); tonearm.classList.remove('playing'); clearInterval(progressInterval); stopEqualizerAnimation(); } } function changeTrack(index) { // Reset current track highlight trackItems.forEach(item => item.classList.remove('active')); // Highlight new track trackItems[index].classList.add('active'); // Update track info trackTitle.textContent = trackData[index].title; trackArtist.textContent = trackData[index].artist; document.querySelector('.total-time').textContent = trackData[index].duration; // Reset progress currentProgress = 0; progressBar.style.width = '0%'; currentTimeDisplay.textContent = '0:00'; // If player was playing, start the new track if (isPlaying) { clearInterval(progressInterval); progressInterval = setInterval(updateProgress, 100); } } function nextTrack() { let currentIndex = 0; trackItems.forEach((item, index) => { if (item.classList.contains('active')) { currentIndex = index; } }); const nextIndex = (currentIndex + 1) % trackItems.length; changeTrack(nextIndex); } function prevTrack() { let currentIndex = 0; trackItems.forEach((item, index) => { if (item.classList.contains('active')) { currentIndex = index; } }); const prevIndex = (currentIndex - 1 + trackItems.length) % trackItems.length; changeTrack(prevIndex); } function animateEqualizer() { equalizerBars.forEach((bar, index) => { const height = Math.floor(Math.random() * 15) + 5; bar.style.height = `${height}px`; // Add animation bar.style.transition = `height ${0.1 + index * 0.01}s ease-in-out`; }); equalizerInterval = setInterval(() => { equalizerBars.forEach((bar, index) => { const height = Math.floor(Math.random() * 15) + 5; bar.style.height = `${height}px`; }); }, 100); } function stopEqualizerAnimation() { clearInterval(equalizerInterval); equalizerBars.forEach(bar => { bar.style.height = '2px'; }); } // Event Listeners playPauseBtn.addEventListener('click', togglePlay); document.querySelector('.skip-forward').addEventListener('click', nextTrack); document.querySelector('.skip-back').addEventListener('click', prevTrack); document.querySelector('.fast-forward').addEventListener('click', function() { currentProgress += 10; if (currentProgress > totalDuration) { currentProgress = totalDuration; } const progressPercent = (currentProgress / totalDuration) * 100; progressBar.style.width = `${progressPercent}%`; currentTimeDisplay.textContent = formatTime(currentProgress); }); document.querySelector('.rewind').addEventListener('click', function() { currentProgress -= 10; if (currentProgress < 0) { currentProgress = 0; } const progressPercent = (currentProgress / totalDuration) * 100; progressBar.style.width = `${progressPercent}%`; currentTimeDisplay.textContent = formatTime(currentProgress); }); trackItems.forEach((item, index) => { item.addEventListener('click', function() { changeTrack(index); if (!isPlaying) togglePlay(); }); }); document.querySelector('.progress-container').addEventListener('click', function(e) { const width = this.clientWidth; const clickX = e.offsetX; const clickPercent = clickX / width; currentProgress = clickPercent * totalDuration; const progressPercent = (currentProgress / totalDuration) * 100; progressBar.style.width = `${progressPercent}%`; currentTimeDisplay.textContent = formatTime(currentProgress); }); // Initial setup for equalizer bars equalizerBars.forEach((bar, index) => { bar.style.height = '2px'; bar.style.transition = 'height 0.3s ease-in-out'; }); // Make vinyl record and tonearm interactive vinylRecord.addEventListener('click', function() { togglePlay(); }); // Cassette tape animation const reels = document.querySelectorAll('.reel'); reels.forEach(reel => { reel.style.transition = 'box-shadow 0.5s linear'; }); // Add hover animations for buttons const buttons = document.querySelectorAll('.control-button'); buttons.forEach(button => { button.addEventListener('mouseenter', function() { this.style.transform = 'scale(1.1)'; }); button.addEventListener('mouseleave', function() { if (!this.classList.contains('play-pause')) { this.style.transform = 'scale(1)'; } }); button.addEventListener('mousedown', function() { this.style.transform = 'scale(0.95)'; }); button.addEventListener('mouseup', function() { this.style.transform = 'scale(1.1)'; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PulseWave Player</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; user-select: none; } body { background-color: #0A0A12; display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; overflow: hidden; color: #E0E0E6; } .player-container { width: 100%; max-width: 700px; height: 700px; position: relative; display: flex; flex-direction: column; padding: 20px; background: linear-gradient(135deg, #13131F 0%, #080810 100%); border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); overflow: hidden; } .player-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; z-index: 2; } .logo { font-size: 1.8rem; font-weight: 700; background: linear-gradient(90deg, #9C27B0, #4A148C); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 0 10px rgba(156, 39, 176, 0.3); } .menu-icon { cursor: pointer; font-size: 1.5rem; color: #6A6A8E; transition: color 0.3s ease; } .menu-icon:hover { color: #E0E0E6; } .visualizer-container { width: 100%; height: 180px; position: relative; margin-bottom: 20px; overflow: hidden; border-radius: 12px; background-color: rgba(6, 6, 12, 0.7); z-index: 2; } .visualizer { width: 100%; height: 100%; display: flex; align-items: flex-end; justify-content: space-between; padding: 0 10px; } .visualizer-bar { width: 6px; border-radius: 3px; background: linear-gradient(to top, #00F5A0, #00D9F5); margin: 0 2px; transform-origin: bottom; box-shadow: 0 0 8px rgba(0, 217, 245, 0.5); } .waveform { width: 100%; height: 60px; position: absolute; bottom: 0; z-index: 1; } .track-info { text-align: center; margin-bottom: 25px; z-index: 2; position: relative; } .track-title { font-size: 1.8rem; font-weight: 600; margin-bottom: 8px; color: #FFFFFF; text-shadow: 0 0 10px rgba(255, 255, 255, 0.2); } .track-artist { font-size: 1rem; color: #9C9CAD; font-weight: 500; } .track-cover { width: 220px; height: 220px; border-radius: 15px; margin: 0 auto 30px; background-size: cover; background-position: center; position: relative; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5); z-index: 2; transition: transform 0.3s ease, box-shadow 0.3s ease; } .track-cover:hover { transform: scale(1.02); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6), 0 0 20px rgba(156, 39, 176, 0.3); } .track-cover::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(156, 39, 176, 0.2) 0%, rgba(0, 0, 0, 0) 100%); } .progress-container { width: 100%; margin-bottom: 25px; position: relative; z-index: 2; } .progress-bg { width: 100%; height: 5px; background-color: rgba(255, 255, 255, 0.1); border-radius: 3px; overflow: hidden; cursor: pointer; } .progress-fill { width: 35%; height: 100%; background: linear-gradient(90deg, #00F5A0, #00D9F5); border-radius: 3px; position: relative; box-shadow: 0 0 8px rgba(0, 217, 245, 0.5); } .progress-time { display: flex; justify-content: space-between; margin-top: 10px; font-size: 0.8rem; color: #9C9CAD; } .controls { display: flex; justify-content: center; align-items: center; margin-bottom: 30px; z-index: 2; } .control-btn { background: none; border: none; outline: none; color: #E0E0E6; font-size: 1.4rem; margin: 0 15px; cursor: pointer; transition: all 0.3s ease; position: relative; } .control-btn:hover { color: #FFFFFF; transform: scale(1.1); } .control-btn.play-pause { width: 60px; height: 60px; background: linear-gradient(135deg, #9C27B0, #4A148C); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-size: 1.8rem; box-shadow: 0 0 20px rgba(156, 39, 176, 0.5); } .control-btn.play-pause:hover { box-shadow: 0 0 30px rgba(156, 39, 176, 0.8); } .control-btn.active { color: #00F5A0; } .volume-container { display: flex; align-items: center; justify-content: center; z-index: 2; } .volume-icon { margin-right: 15px; color: #9C9CAD; font-size: 1.2rem; } .volume-slider { -webkit-appearance: none; width: 120px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.1); outline: none; cursor: pointer; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 15px; height: 15px; border-radius: 50%; background: linear-gradient(135deg, #9C27B0, #4A148C); cursor: pointer; box-shadow: 0 0 10px rgba(156, 39, 176, 0.5); } .volume-slider::-moz-range-thumb { width: 15px; height: 15px; border-radius: 50%; background: linear-gradient(135deg, #9C27B0, #4A148C); cursor: pointer; box-shadow: 0 0 10px rgba(156, 39, 176, 0.5); border: none; } .equalizer-btn { position: absolute; bottom: 20px; right: 20px; width: 40px; height: 40px; border-radius: 50%; background: rgba(20, 20, 30, 0.7); display: flex; justify-content: center; align-items: center; font-size: 1.2rem; color: #9C9CAD; cursor: pointer; z-index: 3; transition: all 0.3s ease; border: 1px solid rgba(156, 39, 176, 0.3); } .equalizer-btn:hover { background: rgba(156, 39, 176, 0.2); color: #FFFFFF; } .glow-effect { position: absolute; width: 300px; height: 300px; border-radius: 50%; background: radial-gradient(circle, rgba(156, 39, 176, 0.2) 0%, rgba(6, 6, 12, 0) 70%); filter: blur(30px); top: 40%; left: 50%; transform: translate(-50%, -50%); z-index: 1; opacity: 0.8; transition: all 1s ease; } .playlist-container { position: absolute; bottom: -200px; left: 0; width: 100%; background: rgba(6, 6, 12, 0.9); backdrop-filter: blur(10px); padding: 20px; border-top-left-radius: 20px; border-top-right-radius: 20px; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); z-index: 10; box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.5); } .playlist-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .playlist-title { font-size: 1.2rem; font-weight: 600; } .close-playlist { cursor: pointer; font-size: 1.2rem; color: #9C9CAD; } .playlist-item { display: flex; align-items: center; padding: 10px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.05); cursor: pointer; transition: all 0.2s ease; } .playlist-item:hover { background: rgba(255, 255, 255, 0.05); border-radius: 8px; padding-left: 10px; } .playlist-item.active { border-left: 3px solid #9C27B0; padding-left: 10px; } .playlist-item-cover { width: 40px; height: 40px; border-radius: 8px; margin-right: 15px; background-size: cover; background-position: center; } .playlist-item-info { flex-grow: 1; } .playlist-item-title { font-size: 0.9rem; margin-bottom: 5px; font-weight: 500; } .playlist-item-artist { font-size: 0.8rem; color: #9C9CAD; } .playlist-item-duration { font-size: 0.8rem; color: #9C9CAD; } .show-playlist .playlist-container { bottom: 0; } /* Glitch effect */ .glitch-container { position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: 0; overflow: hidden; opacity: 0.08; } .glitch-line { position: absolute; width: 110%; height: 1px; background-color: #00F5A0; box-shadow: 0 0 5px rgba(0, 245, 160, 0.8); transform: translateX(-5%); } @keyframes pulse { 0%, 100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.05); } } @keyframes glitch { 0% { transform: translateX(-5%); } 100% { transform: translateX(5%); } } @keyframes waveform { 0% { transform: scaleY(0.8); } 50% { transform: scaleY(1.2); } 100% { transform: scaleY(0.8); } } @media (max-width: 500px) { .player-container { padding: 15px; } .track-cover { width: 180px; height: 180px; margin-bottom: 20px; } .track-title { font-size: 1.5rem; } .controls { margin-bottom: 20px; } .control-btn { margin: 0 10px; font-size: 1.2rem; } .control-btn.play-pause { width: 50px; height: 50px; font-size: 1.5rem; } .volume-slider { width: 80px; } } </style> </head> <body> <div class="player-container"> <div class="player-header"> <div class="logo">PulseWave</div> <div class="menu-icon"> <i class="fas fa-ellipsis-h"></i> </div> </div> <div class="visualizer-container"> <div class="visualizer" id="equalizer"></div> <canvas id="waveform" class="waveform"></canvas> </div> <div class="track-info"> <h2 class="track-title">Neon Reverie</h2> <p class="track-artist">Quantum Echo</p> </div> <div class="track-cover" style="background-image: url('https://images.unsplash.com/photo-1614149162883-504ce4d13909?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1974&q=80')"></div> <div class="progress-container"> <div class="progress-bg" id="progress-bg"> <div class="progress-fill" id="progress-fill"></div> </div> <div class="progress-time"> <span id="current-time">1:45</span> <span id="total-time">5:12</span> </div> </div> <div class="controls"> <button class="control-btn shuffle"> <i class="fas fa-random"></i> </button> <button class="control-btn prev"> <i class="fas fa-step-backward"></i> </button> <button class="control-btn play-pause" id="play-pause-btn"> <i class="fas fa-pause"></i> </button> <button class="control-btn next"> <i class="fas fa-step-forward"></i> </button> <button class="control-btn repeat"> <i class="fas fa-redo"></i> </button> </div> <div class="volume-container"> <div class="volume-icon"> <i class="fas fa-volume-up"></i> </div> <input type="range" min="0" max="100" value="80" class="volume-slider" id="volume-slider"> </div> <div class="equalizer-btn" id="playlist-btn"> <i class="fas fa-list"></i> </div> <div class="glow-effect" id="glow"></div> <div class="glitch-container" id="glitch-container"></div> <div class="playlist-container" id="playlist-container"> <div class="playlist-header"> <h3 class="playlist-title">Your Playlist</h3> <div class="close-playlist" id="close-playlist"> <i class="fas fa-times"></i> </div> </div> <div class="playlist-items"> <div class="playlist-item active"> <div class="playlist-item-cover" style="background-image: url('https://images.unsplash.com/photo-1614149162883-504ce4d13909?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1974&q=80')"></div> <div class="playlist-item-info"> <div class="playlist-item-title">Neon Reverie</div> <div class="playlist-item-artist">Quantum Echo</div> </div> <div class="playlist-item-duration">5:12</div> </div> <div class="playlist-item"> <div class="playlist-item-cover" style="background-image: url('https://images.unsplash.com/photo-1599906823892-fb9da703d50a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGNpdHklMjBuZW9ufGVufDB8fDB8fHwy&auto=format&fit=crop&w=600&q=60')"></div> <div class="playlist-item-info"> <div class="playlist-item-title">Digital Dreams</div> <div class="playlist-item-artist">Neon Collective</div> </div> <div class="playlist-item-duration">4:37</div> </div> <div class="playlist-item"> <div class="playlist-item-cover" style="background-image: url('https://images.unsplash.com/photo-1492684223066-81342ee5ff30?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8ZGFuY2UlMjBtdXNpY3xlbnwwfHwwfHx8Mg%3D%3D&auto=format&fit=crop&w=600&q=60')"></div> <div class="playlist-item-info"> <div class="playlist-item-title">Synthwave Nights</div> <div class="playlist-item-artist">RetroGlide</div> </div> <div class="playlist-item-duration">3:55</div> </div> <div class="playlist-item"> <div class="playlist-item-cover" style="background-image: url('https://images.unsplash.com/photo-1514525253161-7a46d19cd819?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8ZGFuY2UlMjBtdXNpY3xlbnwwfHwwfHx8Mg%3D%3D&auto=format&fit=crop&w=600&q=60')"></div> <div class="playlist-item-info"> <div class="playlist-item-title">Cybernetic Pulse</div> <div class="playlist-item-artist">Digital Frontier</div> </div> <div class="playlist-item-duration">6:21</div> </div> </div> </div> </div> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Generate equalizer bars const equalizer = document.getElementById('equalizer'); const barCount = 50; for (let i = 0; i < barCount; i++) { const bar = document.createElement('div'); bar.className = 'visualizer-bar'; const height = Math.random() * 100 + 15; bar.style.height = `${height}px`; equalizer.appendChild(bar); } // Animate equalizer function animateEqualizer() { const bars = document.querySelectorAll('.visualizer-bar'); bars.forEach(bar => { const height = Math.random() * 100 + 15; bar.style.height = `${height}px`; // Random color variations const hue = Math.random() * 40 + 160; // Cyan to blue-green range bar.style.background = `linear-gradient(to top, #00F5A0, hsl(${hue}, 100%, 65%))`; bar.style.boxShadow = `0 0 8px hsl(${hue}, 100%, 65%, 0.5)`; }); } // Draw waveform const waveformCanvas = document.getElementById('waveform'); const ctx = waveformCanvas.getContext('2d'); function setupCanvas() { const dpr = window.devicePixelRatio || 1; const rect = waveformCanvas.getBoundingClientRect(); waveformCanvas.width = rect.width * dpr; waveformCanvas.height = rect.height * dpr; ctx.scale(dpr, dpr); waveformCanvas.style.width = `${rect.width}px`; waveformCanvas.style.height = `${rect.height}px`; } setupCanvas(); function drawWaveform() { const width = waveformCanvas.getBoundingClientRect().width; const height = waveformCanvas.getBoundingClientRect().height; ctx.clearRect(0, 0, width, height); ctx.beginPath(); ctx.moveTo(0, height / 2); for (let x = 0; x < width; x++) { const y = Math.sin(x * 0.05 + Date.now() * 0.001) * 20 + height / 2; ctx.lineTo(x, y); } ctx.strokeStyle = 'rgba(0, 217, 245, 0.5)'; ctx.lineWidth = 2; ctx.stroke(); // Add glow effect ctx.shadowBlur = 10; ctx.shadowColor = 'rgba(0, 217, 245, 0.8)'; ctx.stroke(); ctx.shadowBlur = 0; } // Generate glitch lines const glitchContainer = document.getElementById('glitch-container'); for (let i = 0; i < 15; i++) { const line = document.createElement('div'); line.className = 'glitch-line'; const top = Math.random() * 100; line.style.top = `${top}%`; line.style.opacity = Math.random() * 0.5 + 0.1; // Add animation with random duration and delay const duration = Math.random() * 2 + 1; const delay = Math.random() * 5; line.style.animation = `glitch ${duration}s ease-in-out infinite alternate ${delay}s`; glitchContainer.appendChild(line); } // Handle play/pause button const playPauseBtn = document.getElementById('play-pause-btn'); let isPlaying = true; playPauseBtn.addEventListener('click', function() { isPlaying = !isPlaying; if (isPlaying) { playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; animateEqualizer(); equalizer.querySelectorAll('.visualizer-bar').forEach(bar => { bar.style.animationPlayState = 'running'; }); } else { playPauseBtn.innerHTML = '<i class="fas fa-play"></i>'; equalizer.querySelectorAll('.visualizer-bar').forEach(bar => { bar.style.animationPlayState = 'paused'; }); } }); // Handle progress bar clicks const progressBg = document.getElementById('progress-bg'); const progressFill = document.getElementById('progress-fill'); progressBg.addEventListener('click', function(e) { const rect = progressBg.getBoundingClientRect(); const percent = (e.clientX - rect.left) / rect.width; progressFill.style.width = `${percent * 100}%`; // Update time display const totalTime = 312; // 5:12 in seconds const currentSeconds = Math.floor(totalTime * percent); document.getElementById('current-time').textContent = formatTime(currentSeconds); }); function formatTime(seconds) { const minutes = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${minutes}:${secs < 10 ? '0' + secs : secs}`; } // Volume slider const volumeSlider = document.getElementById('volume-slider'); volumeSlider.addEventListener('input', function() { const volume = this.value; // In a real app, would set audio volume here // For visual feedback: const volumeIcon = document.querySelector('.volume-icon i'); if (volume > 70) { volumeIcon.className = 'fas fa-volume-up'; } else if (volume > 30) { volumeIcon.className = 'fas fa-volume-down'; } else if (volume > 0) { volumeIcon.className = 'fas fa-volume-off'; } else { volumeIcon.className = 'fas fa-volume-mute'; } }); // Show/hide playlist const playlistBtn = document.getElementById('playlist-btn'); const closePlaylist = document.getElementById('close-playlist'); const playerContainer = document.querySelector('.player-container'); playlistBtn.addEventListener('click', function() { playerContainer.classList.add('show-playlist'); }); closePlaylist.addEventListener('click', function() { playerContainer.classList.remove('show-playlist'); }); // Playlist item click handlers const playlistItems = document.querySelectorAll('.playlist-item'); playlistItems.forEach(item => { item.addEventListener('click', function() { // Remove active class from all items playlistItems.forEach(i => i.classList.remove('active')); // Add active class to clicked item this.classList.add('active'); // Update player with the new track info const title = this.querySelector('.playlist-item-title').textContent; const artist = this.querySelector('.playlist-item-artist').textContent; const cover = this.querySelector('.playlist-item-cover').style.backgroundImage; const duration = this.querySelector('.playlist-item-duration').textContent; document.querySelector('.track-title').textContent = title; document.querySelector('.track-artist').textContent = artist; document.querySelector('.track-cover').style.backgroundImage = cover; document.getElementById('total-time').textContent = duration; document.getElementById('current-time').textContent = '0:00'; progressFill.style.width = '0%'; // Ensure the player is set to playing state isPlaying = true; playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; // Close the playlist playerContainer.classList.remove('show-playlist'); // Trigger visualizations animateEqualizer(); }); }); // Control buttons hover effects const controlBtns = document.querySelectorAll('.control-btn'); controlBtns.forEach(btn => { btn.addEventListener('mouseenter', function() { if (this.classList.contains('play-pause')) { const glow = document.getElementById('glow'); glow.style.opacity = '1'; glow.style.transform = 'translate(-50%, -50%) scale(1.1)'; } }); btn.addEventListener('mouseleave', function() { if (this.classList.contains('play-pause')) { const glow = document.getElementById('glow'); glow.style.opacity = '0.8'; glow.style.transform = 'translate(-50%, -50%) scale(1)'; } }); }); // Animation loops let lastEqUpdate = 0; function animate(time) { // Only update equalizer every 100ms for performance if (time - lastEqUpdate > 100 && isPlaying) { animateEqualizer(); lastEqUpdate = time; } // Update waveform every frame if (isPlaying) { drawWaveform(); } requestAnimationFrame(animate); } requestAnimationFrame(animate); // Add touch effects for mobile const trackCover = document.querySelector('.track-cover'); trackCover.addEventListener('touchstart', function() { this.style.transform = 'scale(0.98)'; }); trackCover.addEventListener('touchend', function() { this.style.transform = 'scale(1)'; }); // Handle window resize window.addEventListener('resize', function() { setupCanvas(); }); // Extra interactive feature for other control buttons document.querySelector('.shuffle').addEventListener('click', function() { this.classList.toggle('active'); }); document.querySelector('.repeat').addEventListener('click', function() { this.classList.toggle('active'); }); }); </script> </body> </html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pulse | Live Music Experience</title> <style> @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@700;800;900&family=Poppins:wght@300;400;500;600&display=swap'); :root { --primary: #ff3864; --secondary: #2de2e6; --tertiary: #7446f9; --dark: #121212; --light: #f5f5f5; --gradient: linear-gradient(135deg, var(--primary) 0%, var(--tertiary) 100%); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Poppins', sans-serif; background-color: var(--dark); color: var(--light); height: 700px; width: 700px; max-width: 100%; max-height: 100%; overflow: hidden; position: relative; } .container { display: flex; flex-direction: column; height: 100%; width: 100%; padding: 20px; position: relative; z-index: 1; } .music-player { display: flex; flex-direction: column; height: 100%; position: relative; } .visualizer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; opacity: 0.3; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .logo { font-family: 'Montserrat', sans-serif; font-weight: 900; font-size: 1.8rem; color: var(--light); letter-spacing: -1px; position: relative; } .logo::after { content: ''; position: absolute; bottom: -2px; left: 0; width: 40%; height: 3px; background: var(--gradient); border-radius: 10px; } .menu-btn { background: none; border: none; color: var(--light); font-size: 1.5rem; cursor: pointer; transition: all 0.3s ease; } .menu-btn:hover { color: var(--primary); } .dual-pane { display: flex; flex-direction: column; flex: 1; gap: 20px; } .track-info { display: flex; gap: 15px; align-items: center; padding: 15px; background: rgba(30, 30, 30, 0.7); border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); } .album-art { width: 80px; height: 80px; border-radius: 8px; overflow: hidden; flex-shrink: 0; position: relative; } .album-art img { width: 100%; height: 100%; object-fit: cover; } .album-glow { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-shadow: 0 0 25px var(--primary); border-radius: 8px; animation: pulse 3s infinite; opacity: 0; } .track-details { flex: 1; } .track-title { font-family: 'Montserrat', sans-serif; font-weight: 800; font-size: 1.3rem; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .track-artist { font-size: 0.9rem; opacity: 0.7; margin-bottom: 10px; } .track-controls { display: flex; align-items: center; gap: 15px; } .player-controls { display: flex; align-items: center; padding: 15px; background: rgba(30, 30, 30, 0.7); border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); } .control-buttons { display: flex; align-items: center; gap: 12px; margin-right: 15px; } .btn { background: none; border: none; color: var(--light); font-size: 1.2rem; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; } .btn:hover { color: var(--secondary); transform: scale(1.1); } .btn.play-pause { width: 50px; height: 50px; background: var(--gradient); border-radius: 50%; color: var(--light); font-size: 1.5rem; } .btn.play-pause:hover { transform: scale(1.05); box-shadow: 0 0 15px rgba(255, 56, 100, 0.5); } .progress-container { flex: 1; display: flex; flex-direction: column; gap: 5px; } .progress-bar { width: 100%; height: 5px; background: rgba(255, 255, 255, 0.2); border-radius: 5px; overflow: hidden; cursor: pointer; } .progress { height: 100%; width: 25%; background: var(--gradient); border-radius: 5px; position: relative; } .progress-ball { position: absolute; right: -5px; top: 50%; transform: translateY(-50%); width: 10px; height: 10px; background: var(--light); border-radius: 50%; box-shadow: 0 0 10px rgba(255, 255, 255, 0.5); } .progress-time { display: flex; justify-content: space-between; font-size: 0.8rem; opacity: 0.8; } .lyrics-container { flex: 1; overflow: hidden; background: rgba(30, 30, 30, 0.7); border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); display: flex; flex-direction: column; } .lyrics-header { padding: 15px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); display: flex; justify-content: space-between; align-items: center; } .lyrics-title { font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 1.1rem; } .toggle-btn { background: none; border: none; color: var(--light); font-size: 0.9rem; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: 5px; } .toggle-btn:hover { color: var(--secondary); } .lyrics-scroll { flex: 1; overflow-y: auto; padding: 15px; position: relative; } .lyrics-scroll::-webkit-scrollbar { width: 5px; } .lyrics-scroll::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.2); border-radius: 10px; } .lyrics-line { font-size: 1.1rem; margin-bottom: 20px; opacity: 0.6; transition: all 0.3s ease; line-height: 1.5; } .lyrics-line.active { font-size: 1.4rem; font-weight: 500; color: var(--light); opacity: 1; transform: scale(1.02); text-shadow: 0 0 10px rgba(255, 255, 255, 0.2); } .lyrics-line.previous { font-size: 0.9rem; opacity: 0.4; } .lyrics-line.next { font-size: 0.9rem; opacity: 0.4; } .player-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; } .audio-features { display: flex; gap: 15px; } .feature-btn { background: none; border: none; color: var(--light); opacity: 0.7; cursor: pointer; transition: all 0.3s ease; font-size: 1.1rem; } .feature-btn:hover, .feature-btn.active { opacity: 1; color: var(--secondary); } .track-meta { font-size: 0.8rem; opacity: 0.7; } @keyframes pulse { 0% { opacity: 0.3; } 50% { opacity: 0.7; } 100% { opacity: 0.3; } } /* Responsive */ @media (min-width: 500px) { .dual-pane { flex-direction: row; } .lyrics-container { width: 60%; } .track-info, .player-controls { width: 40%; } } @media (max-width: 499px) { .track-title { font-size: 1.1rem; } .lyrics-line { font-size: 1rem; } .lyrics-line.active { font-size: 1.2rem; } .logo { font-size: 1.5rem; } } /* Canvas animation */ canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; } /* Beat indicator */ .beat-indicator { position: absolute; top: 15px; right: 15px; width: 10px; height: 10px; background-color: var(--secondary); border-radius: 50%; transition: transform 0.2s ease; } /* Hover effects */ .album-art { transition: transform 0.3s ease, box-shadow 0.3s ease; } .album-art:hover { transform: scale(1.05); box-shadow: 0 0 20px rgba(255, 56, 100, 0.5); } .floating-notes { position: absolute; width: 100%; height: 100%; pointer-events: none; z-index: 0; } .note { position: absolute; font-size: 1.5rem; animation: float 5s linear infinite; opacity: 0; z-index: -1; } @keyframes float { 0% { transform: translateY(100%) rotate(0deg); opacity: 0; } 10% { opacity: 0.7; } 90% { opacity: 0.7; } 100% { transform: translateY(-100vh) rotate(360deg); opacity: 0; } } /* Volume slider */ .volume-control { position: relative; display: flex; align-items: center; gap: 10px; } .volume-slider { width: 0; overflow: hidden; transition: width 0.3s ease; height: 5px; background: rgba(255, 255, 255, 0.2); border-radius: 5px; position: relative; } .volume-slider-inner { height: 100%; width: 70%; background: var(--gradient); border-radius: 5px; } .volume-control:hover .volume-slider { width: 80px; } /* Equalizer */ .equalizer { display: flex; gap: 3px; height: 15px; align-items: flex-end; } .eq-bar { width: 3px; height: 5px; background-color: var(--secondary); border-radius: 2px; animation: equalize 1s ease-in-out infinite; } .eq-bar:nth-child(1) { animation-delay: 0.1s; } .eq-bar:nth-child(2) { animation-delay: 0.3s; } .eq-bar:nth-child(3) { animation-delay: 0.2s; } .eq-bar:nth-child(4) { animation-delay: 0.5s; } .eq-bar:nth-child(5) { animation-delay: 0.4s; } @keyframes equalize { 0% { height: 3px; } 50% { height: 15px; } 100% { height: 3px; } } </style> </head> <body> <canvas id="visualizer"></canvas> <div class="floating-notes" id="floatingNotes"></div> <div class="beat-indicator" id="beatIndicator"></div> <div class="container"> <div class="music-player"> <div class="header"> <div class="logo">PULSE</div> <button class="menu-btn"> <i class="fas fa-ellipsis-h"></i> </button> </div> <div class="dual-pane"> <div class="left-pane"> <div class="track-info"> <div class="album-art"> <img src="https://images.unsplash.com/photo-1614613535308-eb5fbd3d2c17?q=80&w=200&auto=format&fit=crop" alt="Album Art"> <div class="album-glow" id="albumGlow"></div> </div> <div class="track-details"> <div class="track-title">Neon Dreams</div> <div class="track-artist">Midnight Pulse</div> <div class="track-controls"> <button class="btn"> <i class="fas fa-heart"></i> </button> <button class="btn"> <i class="fas fa-plus"></i> </button> <div class="equalizer"> <div class="eq-bar"></div> <div class="eq-bar"></div> <div class="eq-bar"></div> <div class="eq-bar"></div> <div class="eq-bar"></div> </div> </div> </div> </div> <div class="player-controls"> <div class="control-buttons"> <button class="btn"> <i class="fas fa-step-backward"></i> </button> <button class="btn play-pause" id="playPauseBtn"> <i class="fas fa-play" id="playIcon"></i> </button> <button class="btn"> <i class="fas fa-step-forward"></i> </button> </div> <div class="progress-container"> <div class="progress-bar" id="progressBar"> <div class="progress" id="progress"> <div class="progress-ball"></div> </div> </div> <div class="progress-time"> <span>1:23</span> <span>4:56</span> </div> </div> </div> </div> <div class="lyrics-container"> <div class="lyrics-header"> <div class="lyrics-title">Live Lyrics</div> <button class="toggle-btn"> <i class="fas fa-sync-alt"></i> <span>Auto-scroll</span> </button> </div> <div class="lyrics-scroll" id="lyricsScroll"> <div class="lyrics-line previous">City lights reflect in puddles on the ground</div> <div class="lyrics-line previous">Memories fade as rain comes pouring down</div> <div class="lyrics-line active">Electric dreams flowing through my veins</div> <div class="lyrics-line next">Neon signs blinking through the haze</div> <div class="lyrics-line next">Strangers passing by without a sound</div> <div class="lyrics-line next">Another night in this sleepless town</div> <div class="lyrics-line next">The pulse of the city, beating like a drum</div> <div class="lyrics-line next">Echoes of footsteps, I'm on the run</div> <div class="lyrics-line next">Digital whispers calling my name</div> <div class="lyrics-line next">In this electric world, nothing's the same</div> </div> </div> </div> <div class="player-footer"> <div class="audio-features"> <button class="feature-btn active"> <i class="fas fa-random"></i> </button> <button class="feature-btn"> <i class="fas fa-redo"></i> </button> <div class="volume-control"> <button class="feature-btn"> <i class="fas fa-volume-up"></i> </button> <div class="volume-slider"> <div class="volume-slider-inner"></div> </div> </div> </div> <div class="track-meta"> LIVE · SYNTH WAVE · 128 BPM </div> </div> </div> </div> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> // Elements const playPauseBtn = document.getElementById('playPauseBtn'); const playIcon = document.getElementById('playIcon'); const progress = document.getElementById('progress'); const progressBar = document.getElementById('progressBar'); const lyricsScroll = document.getElementById('lyricsScroll'); const albumGlow = document.getElementById('albumGlow'); const beatIndicator = document.getElementById('beatIndicator'); const floatingNotes = document.getElementById('floatingNotes'); const canvas = document.getElementById('visualizer'); const ctx = canvas.getContext('2d'); // Visualizer setup canvas.width = window.innerWidth; canvas.height = window.innerHeight; // State let isPlaying = false; let currentLyricIndex = 2; // Start with the "active" line const lyrics = document.querySelectorAll('.lyrics-line'); let lyricChangeInterval; let visualizerAnimationId; let beatInterval; // Initialize window.addEventListener('load', initializePlayer); window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); function initializePlayer() { // Add event listeners playPauseBtn.addEventListener('click', togglePlayPause); progressBar.addEventListener('click', scrubProgress); // Initialize visualizer drawVisualizer(); // Floating music notes createFloatingNotes(); } function togglePlayPause() { isPlaying = !isPlaying; if (isPlaying) { playIcon.classList.remove('fa-play'); playIcon.classList.add('fa-pause'); albumGlow.style.opacity = '1'; startLyricsScroll(); startBeatAnimation(); } else { playIcon.classList.remove('fa-pause'); playIcon.classList.add('fa-play'); albumGlow.style.opacity = '0'; clearInterval(lyricChangeInterval); clearInterval(beatInterval); } } function scrubProgress(e) { const scrubTime = (e.offsetX / progressBar.offsetWidth); progress.style.width = `${scrubTime * 100}%`; } function startLyricsScroll() { // Reset existing interval if any clearInterval(lyricChangeInterval); // Start scrolling lyrics lyricChangeInterval = setInterval(() => { // Update current active lyric lyrics.forEach(line => line.classList.remove('active', 'previous', 'next')); // Increment lyric index currentLyricIndex = (currentLyricIndex + 1) % lyrics.length; // Set new classes lyrics[currentLyricIndex].classList.add('active'); // Set previous lines for (let i = 1; i <= 2; i++) { const prevIndex = (currentLyricIndex - i + lyrics.length) % lyrics.length; if (prevIndex >= 0) lyrics[prevIndex].classList.add('previous'); } // Set next lines for (let i = 1; i <= 2; i++) { const nextIndex = (currentLyricIndex + i) % lyrics.length; if (nextIndex < lyrics.length) lyrics[nextIndex].classList.add('next'); } // Scroll to active lyric const activeElement = lyrics[currentLyricIndex]; lyricsScroll.scrollTop = activeElement.offsetTop - lyricsScroll.offsetTop - 100; // Update progress bar const progressPercent = (currentLyricIndex / (lyrics.length - 1)) * 100; progress.style.width = `${progressPercent}%`; }, 3000); // Change lyrics every 3 seconds } function startBeatAnimation() { // Beat indicator animation beatInterval = setInterval(() => { beatIndicator.style.transform = 'scale(1.5)'; setTimeout(() => { beatIndicator.style.transform = 'scale(1)'; }, 100); }, 500); // Beat every half second } function createFloatingNotes() { const notes = ['♪', '♫', '♬', '♩']; setInterval(() => { if (!isPlaying) return; const note = document.createElement('div'); note.className = 'note'; note.textContent = notes[Math.floor(Math.random() * notes.length)]; note.style.left = `${Math.random() * 100}%`; note.style.color = getRandomColor(); note.style.animationDuration = `${5 + Math.random() * 5}s`; floatingNotes.appendChild(note); // Remove note after animation completes setTimeout(() => { note.remove(); }, 10000); }, 800); } function getRandomColor() { const colors = ['#ff3864', '#2de2e6', '#7446f9', '#f9c846']; return colors[Math.floor(Math.random() * colors.length)]; } function drawVisualizer() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Only draw active visualization if music is playing if (isPlaying) { // Draw flowing waves const time = Date.now() * 0.001; const numberOfWaves = 5; for (let w = 0; w < numberOfWaves; w++) { ctx.beginPath(); // Set different colors for each wave let hue = (time * 10 + w * 30) % 360; ctx.strokeStyle = `hsla(${hue}, 100%, 50%, 0.1)`; ctx.lineWidth = 2; // Draw the wave for (let x = 0; x < canvas.width; x += 5) { // Create different wave patterns const y = Math.sin(x * 0.01 + time + w) * 50 + Math.sin(x * 0.02 + time * 1.5) * 20 + Math.sin(x * 0.003 + time * 0.7) * 30; if (x === 0) { ctx.moveTo(x, canvas.height / 2 + y); } else { ctx.lineTo(x, canvas.height / 2 + y); } } ctx.stroke(); } // Create circular beat pulses const numCircles = 3; for (let i = 0; i < numCircles; i++) { const radius = ((time * 100) + i * 100) % Math.max(canvas.width, canvas.height); const opacity = 1 - (radius / Math.max(canvas.width, canvas.height)); if (opacity > 0) { ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, Math.PI * 2); ctx.strokeStyle = `rgba(46, 226, 230, ${opacity * 0.3})`; ctx.lineWidth = 2; ctx.stroke(); } } } else { // Simple static background when paused drawStaticBackground(); } visualizerAnimationId = requestAnimationFrame(drawVisualizer); } function drawStaticBackground() { // Draw subtle static background ctx.fillStyle = 'rgba(20, 20, 20, 0.1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Add a few static dots for (let i = 0; i < 50; i++) { const x = Math.random() * canvas.width; const y = Math.random() * canvas.height; const radius = Math.random() * 2; ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2); ctx.fillStyle = 'rgba(255, 255, 255, 0.1)'; ctx.fill(); } } </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Modulax Music Player</title> <style> :root { --primary-color: #2c2c34; --secondary-color: #f2f2f2; --accent-color: #7f5af0; --accent-secondary: #2cb67d; --text-color: #fffffe; --background-color: #16161a; --panel-color: #242629; --transition-speed: 0.3s; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--background-color); color: var(--text-color); height: 700px; width: 700px; max-width: 100%; max-height: 100%; overflow: hidden; display: flex; flex-direction: column; } .player-container { display: flex; flex-direction: column; height: 100%; padding: 20px; gap: 20px; } /* Header Section */ .header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .logo { font-size: 24px; font-weight: 700; background: linear-gradient(90deg, var(--accent-color), var(--accent-secondary)); -webkit-background-clip: text; background-clip: text; color: transparent; letter-spacing: -0.5px; } .user-profile { display: flex; align-items: center; gap: 10px; } .user-avatar { width: 30px; height: 30px; border-radius: 50%; background-color: var(--accent-color); display: grid; place-items: center; color: var(--text-color); font-weight: bold; cursor: pointer; transition: transform var(--transition-speed); } .user-avatar:hover { transform: scale(1.1); } /* Main Content */ .content { display: grid; grid-template-columns: 1fr 2fr; gap: 20px; flex-grow: 1; overflow: hidden; } /* Sidebar */ .sidebar { background-color: var(--panel-color); border-radius: 12px; padding: 15px; display: flex; flex-direction: column; gap: 15px; overflow-y: auto; } .sidebar-header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .custom-controls { display: grid; grid-template-columns: repeat(2, 1fr); grid-gap: 10px; } .control-module { background-color: rgba(127, 90, 240, 0.1); border-radius: 6px; padding: 10px; cursor: move; transition: background-color var(--transition-speed); text-align: center; font-size: 12px; } .control-module:hover { background-color: rgba(127, 90, 240, 0.2); } .active-module { background-color: rgba(127, 90, 240, 0.3); position: relative; } .active-module::after { content: "✓"; position: absolute; top: 5px; right: 5px; font-size: 10px; color: var(--accent-color); } .playlists { flex-grow: 1; overflow-y: auto; } .playlist-header { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; margin-bottom: 15px; } .playlist-item { display: flex; align-items: center; padding: 10px; border-radius: 6px; margin-bottom: 8px; cursor: pointer; transition: background-color var(--transition-speed); position: relative; } .playlist-item:hover { background-color: rgba(255, 255, 255, 0.05); } .playlist-item.active { background-color: rgba(127, 90, 240, 0.2); } .playlist-cover { width: 40px; height: 40px; border-radius: 6px; margin-right: 10px; object-fit: cover; } .playlist-info { flex-grow: 1; } .playlist-title { font-size: 14px; font-weight: 500; } .playlist-count { font-size: 12px; color: rgba(255, 255, 255, 0.5); margin-top: 2px; } .droppable { background-color: rgba(44, 182, 125, 0.2); border: 2px dashed var(--accent-secondary); } /* Main Player */ .main-player { display: flex; flex-direction: column; gap: 20px; overflow-y: auto; } .now-playing { background-color: var(--panel-color); border-radius: 12px; padding: 20px; display: flex; flex-direction: column; align-items: center; position: relative; } .album-art-container { position: relative; width: 200px; height: 200px; margin-bottom: 20px; perspective: 1000px; cursor: pointer; } .album-art { width: 100%; height: 100%; border-radius: 10px; object-fit: cover; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); transition: transform 0.8s; transform-style: preserve-3d; } .album-art-container:hover .album-art { transform: rotateY(180deg); } .album-back { position: absolute; width: 100%; height: 100%; top: 0; left: 0; border-radius: 10px; background-color: var(--panel-color); backface-visibility: hidden; transform: rotateY(180deg); display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 20px; text-align: center; gap: 10px; } .track-info { text-align: center; width: 100%; } .track-title { font-size: 20px; font-weight: 600; margin-bottom: 5px; } .track-artist { font-size: 16px; color: rgba(255, 255, 255, 0.7); margin-bottom: 20px; } .progress-container { width: 100%; margin-bottom: 15px; } .progress-bar { height: 6px; width: 100%; background-color: rgba(255, 255, 255, 0.1); border-radius: 3px; position: relative; overflow: hidden; cursor: pointer; } .progress { height: 100%; width: 30%; background: linear-gradient(90deg, var(--accent-color), var(--accent-secondary)); position: absolute; border-radius: 3px; transition: width 0.1s linear; } .time-info { display: flex; justify-content: space-between; width: 100%; margin-top: 5px; font-size: 12px; color: rgba(255, 255, 255, 0.5); } .player-controls { display: flex; align-items: center; justify-content: center; gap: 20px; width: 100%; } .control-btn { background: none; border: none; color: var(--text-color); font-size: 24px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: transform var(--transition-speed), color var(--transition-speed); width: 40px; height: 40px; border-radius: 50%; } .control-btn:hover { color: var(--accent-color); transform: scale(1.1); } .play-btn { background-color: var(--accent-color); color: var(--background-color); width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 28px; } .play-btn:hover { background-color: var(--accent-secondary); color: var(--background-color); } .additional-controls { display: flex; justify-content: space-between; width: 100%; margin-top: 15px; } .volume-control { display: flex; align-items: center; gap: 10px; } .volume-slider { width: 80px; height: 4px; -webkit-appearance: none; background-color: rgba(255, 255, 255, 0.1); border-radius: 2px; outline: none; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background-color: var(--accent-color); cursor: pointer; } .extra-controls { display: flex; gap: 15px; } .extra-btn { background: none; border: none; color: rgba(255, 255, 255, 0.7); font-size: 16px; cursor: pointer; transition: color var(--transition-speed); } .extra-btn:hover { color: var(--accent-color); } .active-btn { color: var(--accent-color); } .tracks-container { background-color: var(--panel-color); border-radius: 12px; padding: 20px; flex-grow: 1; overflow-y: auto; } .tracks-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .tracks-filter { display: flex; gap: 10px; } .filter-btn { background: none; border: none; color: rgba(255, 255, 255, 0.5); font-size: 14px; cursor: pointer; transition: color var(--transition-speed); padding: 5px 10px; border-radius: 4px; } .filter-btn:hover, .filter-btn.active { color: var(--text-color); background-color: rgba(255, 255, 255, 0.1); } .track-list { display: flex; flex-direction: column; gap: 10px; } .track-item { display: flex; align-items: center; padding: 10px; border-radius: 6px; transition: background-color var(--transition-speed); cursor: pointer; position: relative; } .track-item:hover { background-color: rgba(255, 255, 255, 0.05); } .track-item.playing { background-color: rgba(127, 90, 240, 0.2); } .track-number { width: 25px; text-align: center; font-size: 14px; color: rgba(255, 255, 255, 0.5); } .track-item.playing .track-number { color: var(--accent-color); } .track-thumbnail { width: 40px; height: 40px; border-radius: 4px; margin: 0 10px; object-fit: cover; } .track-item-info { flex-grow: 1; } .track-item-title { font-size: 14px; font-weight: 500; } .track-item-artist { font-size: 12px; color: rgba(255, 255, 255, 0.5); margin-top: 2px; } .track-duration { font-size: 14px; color: rgba(255, 255, 255, 0.5); margin-right: 10px; } .track-actions { opacity: 0; display: flex; gap: 10px; transition: opacity var(--transition-speed); } .track-item:hover .track-actions { opacity: 1; } .track-action-btn { background: none; border: none; color: rgba(255, 255, 255, 0.7); font-size: 14px; cursor: pointer; transition: color var(--transition-speed); } .track-action-btn:hover { color: var(--accent-color); } /* Drag indicator */ .drag-indicator { position: absolute; width: 100%; height: 3px; background-color: var(--accent-color); opacity: 0; transition: opacity var(--transition-speed); } .drag-indicator.top { top: 0; } .drag-indicator.bottom { bottom: 0; } .drag-active .drag-indicator { opacity: 1; } /* Animations */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .playing .track-item-title { position: relative; } .playing .track-item-title::after { content: ""; position: absolute; bottom: -2px; left: 0; width: 100%; height: 2px; background: linear-gradient(90deg, var(--accent-color), var(--accent-secondary)); transform: scaleX(0); transform-origin: left; animation: track-progress 30s linear infinite; } @keyframes track-progress { 0% { transform: scaleX(0); } 100% { transform: scaleX(1); } } /* Visualizer */ .visualizer { position: absolute; bottom: 20px; left: 20px; right: 20px; height: 30px; display: flex; justify-content: space-between; align-items: flex-end; opacity: 0; transition: opacity var(--transition-speed); } .now-playing:hover .visualizer { opacity: 1; } .visualizer-bar { width: 4px; background-color: var(--accent-color); border-radius: 2px; animation: visualize 1.5s ease-in-out infinite; } @keyframes visualize { 0%, 100% { height: 5px; } 50% { height: 20px; } } .visualizer-bar:nth-child(1) { animation-delay: 0.0s; } .visualizer-bar:nth-child(2) { animation-delay: 0.1s; } .visualizer-bar:nth-child(3) { animation-delay: 0.2s; } .visualizer-bar:nth-child(4) { animation-delay: 0.3s; } .visualizer-bar:nth-child(5) { animation-delay: 0.4s; } .visualizer-bar:nth-child(6) { animation-delay: 0.5s; } .visualizer-bar:nth-child(7) { animation-delay: 0.6s; } .visualizer-bar:nth-child(8) { animation-delay: 0.7s; } .visualizer-bar:nth-child(9) { animation-delay: 0.8s; } .visualizer-bar:nth-child(10) { animation-delay: 0.9s; } .visualizer-bar:nth-child(11) { animation-delay: 1.0s; } .visualizer-bar:nth-child(12) { animation-delay: 1.1s; } .visualizer-bar:nth-child(13) { animation-delay: 1.2s; } .visualizer-bar:nth-child(14) { animation-delay: 1.3s; } .visualizer-bar:nth-child(15) { animation-delay: 1.4s; } /* Responsive Design */ @media (max-width: 700px) { .content { grid-template-columns: 1fr; grid-template-rows: auto 1fr; } .sidebar { grid-row: 1; max-height: 150px; } .custom-controls { grid-template-columns: repeat(4, 1fr); } .main-player { grid-row: 2; } .album-art-container { width: 150px; height: 150px; } .track-item { padding: 8px 5px; } .track-thumbnail { width: 30px; height: 30px; margin: 0 5px; } .track-actions { display: none; } } @media (max-width: 500px) { .player-container { padding: 10px; gap: 10px; } .content { gap: 10px; } .sidebar, .now-playing, .tracks-container { padding: 10px; } .album-art-container { width: 120px; height: 120px; margin-bottom: 10px; } .track-title { font-size: 16px; } .track-artist { font-size: 14px; margin-bottom: 10px; } .custom-controls { grid-template-columns: repeat(2, 1fr); grid-gap: 5px; } .player-controls { gap: 10px; } .control-btn { font-size: 20px; width: 30px; height: 30px; } .play-btn { width: 40px; height: 40px; font-size: 24px; } } </style> </head> <body> <div class="player-container"> <div class="header"> <div class="logo">Modulax</div> <div class="user-profile"> <div class="user-avatar">M</div> </div> </div> <div class="content"> <!-- Sidebar with customizable controls and playlists --> <div class="sidebar"> <div class="sidebar-header"> <h3>Control Modules</h3> </div> <div class="custom-controls"> <div class="control-module active-module" draggable="true">Equalizer</div> <div class="control-module" draggable="true">Effects</div> <div class="control-module active-module" draggable="true">Visualizer</div> <div class="control-module" draggable="true">Lyrics</div> </div> <div class="playlist-header"> <h3>Playlists</h3> </div> <div class="playlists"> <div class="playlist-item active"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSIjN2Y1YWYwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMwIiBmaWxsPSIjN2Y1YWYwIi8+PGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iMTUiIGZpbGw9IiMyNDI2MjkiLz48L3N2Zz4=" alt="Discover Weekly" class="playlist-cover"> <div class="playlist-info"> <div class="playlist-title">Discover Weekly</div> <div class="playlist-count">15 tracks</div> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> <div class="playlist-item"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSIjMmNiNjdkIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxwb2x5Z29uIHBvaW50cz0iMjUsMjUgNzUsMjUgNTAsNzUiIGZpbGw9IiMyY2I2N2QiLz48L3N2Zz4=" alt="Chill Vibes" class="playlist-cover"> <div class="playlist-info"> <div class="playlist-title">Chill Vibes</div> <div class="playlist-count">28 tracks</div> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> <div class="playlist-item"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSIjZmY4OTA2Ij48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxyZWN0IHg9IjI1IiB5PSIyNSIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiBmaWxsPSIjZmY4OTA2Ii8+PC9zdmc+" alt="Workout Mix" class="playlist-cover"> <div class="playlist-info"> <div class="playlist-title">Workout Mix</div> <div class="playlist-count">32 tracks</div> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> <div class="playlist-item"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSIjZTQ0YzU1Ij48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjI1IiBjeT0iMjUiIHI9IjE1IiBmaWxsPSIjZTQ0YzU1Ii8+PGNpcmNsZSBjeD0iNzUiIGN5PSIyNSIgcj0iMTUiIGZpbGw9IiNlNDRjNTUiLz48Y2lyY2xlIGN4PSI1MCIgY3k9IjY1IiByPSIyNSIgZmlsbD0iIzI0MjYyOSIvPjxwYXRoIGQ9Ik0zNSw2NSBDMzUsNzMuMjg0IDQxLjcxNiw4MCA1MCw4MCBDNTguMjg0LDgwIDY1LDczLjI4NCA2NSw2NSIgc3Ryb2tlPSIjZTQ0YzU1IiBzdHJva2Utd2lkdGg9IjUiIGZpbGw9Im5vbmUiLz48L3N2Zz4=" alt="Feel Good" class="playlist-cover"> <div class="playlist-info"> <div class="playlist-title">Feel Good</div> <div class="playlist-count">45 tracks</div> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> <div class="playlist-item"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSIjNmM3NTdkIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjUwIiBjeT0iMzAiIHI9IjIwIiBmaWxsPSIjNmM3NTdkIi8+PHBhdGggZD0iTTMwLDcwIEg3MCBMNTAsMzAgWiIgZmlsbD0iIzZjNzU3ZCIvPjwvc3ZnPg==" alt="Late Night" class="playlist-cover"> <div class="playlist-info"> <div class="playlist-title">Late Night</div> <div class="playlist-count">20 tracks</div> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> </div> </div> <!-- Main Player --> <div class="main-player"> <!-- Now Playing --> <div class="now-playing"> <div class="album-art-container"> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMDAgMzAwIj48cmVjdCB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjE1MCIgY3k9IjE1MCIgcj0iMTAwIiBmaWxsPSIjN2Y1YWYwIi8+PGNpcmNsZSBjeD0iMTUwIiBjeT0iMTUwIiByPSI3NSIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjE1MCIgY3k9IjE1MCIgcj0iMjUiIGZpbGw9IiM3ZjVhZjAiLz48L3N2Zz4=" alt="Album Art" class="album-art"> <div class="album-back"> <h3>Prismatic Soul</h3> <p>Cosmic synthwave album exploring electronic soundscapes with ethereal vocals</p> <p><strong>Released:</strong> 2023</p> <p><strong>Label:</strong> Future Vision Records</p> </div> </div> <div class="track-info"> <div class="track-title">Digital Horizons</div> <div class="track-artist">Neon Cascade</div> </div> <div class="progress-container"> <div class="progress-bar"> <div class="progress"></div> </div> <div class="time-info"> <span class="current-time">1:45</span> <span class="total-time">5:32</span> </div> </div> <div class="player-controls"> <button class="control-btn shuffle-btn"> <i>⇄</i> </button> <button class="control-btn prev-btn"> <i>⏮</i> </button> <button class="control-btn play-btn"> <i>▶</i> </button> <button class="control-btn next-btn"> <i>⏭</i> </button> <button class="control-btn repeat-btn"> <i>🔁</i> </button> </div> <div class="additional-controls"> <div class="volume-control"> <span class="volume-icon">🔊</span> <input type="range" class="volume-slider" min="0" max="100" value="80"> </div> <div class="extra-controls"> <button class="extra-btn eq-btn active-btn" title="Equalizer">EQ</button> <button class="extra-btn lyrics-btn" title="Lyrics">🎵</button> <button class="extra-btn add-btn" title="Add to playlist">+</button> </div> </div> <div class="visualizer"> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> </div> </div> <!-- Tracks List --> <div class="tracks-container"> <div class="tracks-header"> <h3>Discover Weekly</h3> <div class="tracks-filter"> <button class="filter-btn active">All</button> <button class="filter-btn">Recent</button> <button class="filter-btn">Popular</button> </div> </div> <div class="track-list"> <div class="track-item playing" draggable="true"> <div class="track-number">1</div> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMwIiBmaWxsPSIjN2Y1YWYwIi8+PGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iMTUiIGZpbGw9IiMyNDI2MjkiLz48L3N2Zz4=" alt="Track thumbnail" class="track-thumbnail"> <div class="track-item-info"> <div class="track-item-title">Digital Horizons</div> <div class="track-item-artist">Neon Cascade</div> </div> <div class="track-duration">5:32</div> <div class="track-actions"> <button class="track-action-btn">❤️</button> <button class="track-action-btn">⋮</button> </div> <div class="drag-indicator top"></div> <div class="drag-indicator bottom"></div> </div> <div class="track-item" draggable="true"> <div class="track-number">2</div> <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzI0MjYyOSIvPjxyZWN0IHg9IjI1IiB5PSIyNSIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiBmaWxsPSIjMmNiNjdkIi8+PC9zdmc+" alt="Track thumbnail" class="track-thumbnail"> <div class="track-item-info"> <div class="track-item-title">Vel
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pulse - Kinetic Music Player</title> <style> :root { --primary-color: #7c9ff3; --secondary-color: #e8c1fe; --tertiary-color: #b1f8cf; --background-start: #f5f7ff; --background-end: #eff1fa; --text-primary: #2d3748; --text-secondary: #4a5568; --shadow-sm: 0 4px 6px rgba(174, 174, 192, 0.1); --shadow-md: 0 8px 15px rgba(174, 174, 192, 0.15); --transition-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); --transition-smooth: cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background: linear-gradient(135deg, var(--background-start), var(--background-end)); color: var(--text-primary); height: 700px; width: 700px; display: flex; justify-content: center; align-items: center; overflow: hidden; } .music-player { width: 85%; max-width: 480px; background: rgba(255, 255, 255, 0.92); backdrop-filter: blur(10px); border-radius: 24px; padding: 32px; box-shadow: var(--shadow-md); transition: transform 0.5s var(--transition-bounce); position: relative; } .music-player:hover { transform: translateY(-5px); } .player-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .pulse-logo { font-weight: 700; font-size: 1.5rem; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; position: relative; } .pulse-logo::after { content: "♫"; position: absolute; font-size: 0.8rem; top: -8px; right: -12px; animation: pulse 2s infinite; } .menu-btn { background: none; border: none; cursor: pointer; color: var(--text-secondary); font-size: 1.5rem; transition: transform 0.3s var(--transition-smooth); } .menu-btn:hover { transform: rotate(90deg); color: var(--primary-color); } .album-art { position: relative; width: 100%; aspect-ratio: 1; border-radius: 16px; margin-bottom: 24px; overflow: hidden; box-shadow: var(--shadow-sm); } .album-art img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--transition-smooth); } .album-art:hover img { transform: scale(1.03); } .album-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(0deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 50%); display: flex; align-items: flex-end; padding: 20px; opacity: 0; transition: opacity 0.3s var(--transition-smooth); } .album-art:hover .album-overlay { opacity: 1; } .album-overlay-text { color: white; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } .track-info { text-align: center; margin-bottom: 28px; } .track-title { font-size: 1.4rem; font-weight: 700; margin-bottom: 6px; transition: color 0.3s var(--transition-smooth); } .track-artist { font-size: 0.95rem; color: var(--text-secondary); font-weight: 500; } .progress-container { width: 100%; height: 48px; position: relative; margin-bottom: 24px; display: flex; align-items: center; } .progress-bar { width: 100%; height: 6px; background: linear-gradient(90deg, var(--tertiary-color) 0%, var(--secondary-color) 50%, var(--primary-color) 100%); border-radius: 3px; position: relative; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); overflow: hidden; cursor: pointer; } .progress-fill { position: absolute; top: 0; left: 0; height: 100%; width: 35%; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); border-radius: 3px; transition: width 0.1s var(--transition-smooth); } .progress-handle { position: absolute; top: 50%; left: 35%; /* Same as progress-fill width */ transform: translate(-50%, -50%); width: 18px; height: 18px; background: white; border-radius: 50%; box-shadow: var(--shadow-sm); cursor: grab; transition: transform 0.2s var(--transition-bounce); z-index: 10; } .progress-handle:hover { transform: translate(-50%, -50%) scale(1.2); } .progress-handle:active { transform: translate(-50%, -50%) scale(1.1); cursor: grabbing; } .time-display { display: flex; justify-content: space-between; font-size: 0.75rem; color: var(--text-secondary); margin-top: 6px; font-weight: 500; } .controls { display: flex; justify-content: center; align-items: center; gap: 24px; } .control-btn { background: none; border: none; cursor: pointer; transition: all 0.2s var(--transition-bounce); color: var(--text-primary); display: flex; align-items: center; justify-content: center; } .control-btn:hover { color: var(--primary-color); transform: translateY(-2px); } .control-btn:active { transform: translateY(0); } .play-btn { width: 56px; height: 56px; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); border-radius: 50%; color: white; box-shadow: 0 4px 15px rgba(124, 159, 243, 0.3); font-size: 1.5rem; display: flex; align-items: center; justify-content: center; position: relative; z-index: 1; transition: transform 0.2s var(--transition-bounce), box-shadow 0.2s var(--transition-smooth); } .play-btn::before { content: ''; position: absolute; top: -3px; left: -3px; right: -3px; bottom: -3px; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); border-radius: 50%; z-index: -1; opacity: 0.4; filter: blur(8px); transition: all 0.2s var(--transition-smooth); } .play-btn:hover { transform: scale(1.1); box-shadow: 0 8px 20px rgba(124, 159, 243, 0.4); } .play-btn:hover::before { opacity: 0.6; filter: blur(12px); } .play-btn:active { transform: scale(0.95); } .equalizer { display: none; height: 30px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; align-items: flex-end; gap: 3px; } .equalizer.active { display: flex; } .eq-bar { width: 3px; background-color: rgba(255, 255, 255, 0.8); border-radius: 1px; } .volume-container { position: relative; display: flex; align-items: center; margin-top: 24px; gap: 12px; } .volume-icon { color: var(--text-secondary); cursor: pointer; transition: color 0.2s var(--transition-smooth); } .volume-icon:hover { color: var(--primary-color); } .volume-slider { flex: 1; height: 4px; background: linear-gradient(90deg, var(--tertiary-color), var(--primary-color)); border-radius: 2px; position: relative; cursor: pointer; } .volume-fill { position: absolute; left: 0; top: 0; height: 100%; width: 70%; background: var(--primary-color); border-radius: 2px; } .volume-handle { position: absolute; top: 50%; left: 70%; transform: translate(-50%, -50%); width: 12px; height: 12px; background: white; border-radius: 50%; box-shadow: var(--shadow-sm); transition: transform 0.2s var(--transition-bounce); } .volume-handle:hover { transform: translate(-50%, -50%) scale(1.3); } .playlist-button { position: absolute; right: 32px; bottom: 32px; width: 40px; height: 40px; border-radius: 50%; background: white; box-shadow: var(--shadow-sm); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s var(--transition-bounce); border: none; color: var(--text-secondary); } .playlist-button:hover { transform: translateY(-3px) scale(1.05); box-shadow: var(--shadow-md); color: var(--primary-color); } .sound-wave-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; pointer-events: none; opacity: 0.75; overflow: hidden; } .sound-bar { width: 2px; background: var(--primary-color); border-radius: 1px; opacity: 0.5; transform-origin: bottom; } /* Responsive styles */ @media (max-width: 500px) { .music-player { width: 95%; padding: 24px; } .controls { gap: 16px; } .play-btn { width: 50px; height: 50px; } } /* Keyframe animations */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes sound-wave { 0% { height: 3px; } 50% { height: var(--height); } 100% { height: 3px; } } /* Added visual effects for kinetic motion */ .vibration-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.5; } .vibration-particles { position: absolute; border-radius: 50%; background: var(--primary-color); opacity: 0; animation: fadeOut 1s forwards; } @keyframes fadeOut { 0% { opacity: 0.7; transform: translate(0, 0); } 100% { opacity: 0; transform: translate(var(--tx), var(--ty)); } } .ripple { position: absolute; border-radius: 50%; transform: scale(0); background: rgba(124, 159, 243, 0.4); animation: ripple 0.8s linear; } @keyframes ripple { to { transform: scale(4); opacity: 0; } } </style> </head> <body> <div class="music-player"> <div class="player-header"> <div class="pulse-logo">Pulse</div> <button class="menu-btn">⋮</button> </div> <div class="album-art"> <img src="https://images.unsplash.com/photo-1500462918059-b1a0cb512f1d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&q=80&w=600" alt="Album Art"> <div class="album-overlay"> <div class="album-overlay-text"> <div>Feel the Rhythm</div> <div style="font-size: 0.8rem; opacity: 0.8;">Tap to expand</div> </div> </div> </div> <div class="track-info"> <div class="track-title">Celestial Cascade</div> <div class="track-artist">Aether Waves</div> </div> <div class="progress-container"> <div class="progress-bar" id="progressBar"> <div class="progress-fill" id="progressFill"></div> <div class="progress-handle" id="progressHandle"></div> <div class="sound-wave-container" id="soundWaveContainer"></div> </div> <div class="vibration-container" id="vibrationContainer"></div> </div> <div class="time-display"> <div class="time-current">1:47</div> <div class="time-total">5:03</div> </div> <div class="controls"> <button class="control-btn"> <svg width="24" height="24" fill="none" viewBox="0 0 24 24"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17.75 19.25L6.25 12L17.75 4.75V19.25Z"></path> </svg> </button> <button class="play-btn" id="playBtn"> <svg width="24" height="24" fill="none" viewBox="0 0 24 24" id="playIcon"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M18.25 12L5.75 5.75V18.25L18.25 12Z"></path> </svg> <svg width="24" height="24" fill="none" viewBox="0 0 24 24" style="display: none;" id="pauseIcon"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 6.75V17.25"></path> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8.75 6.75V17.25"></path> </svg> <div class="equalizer" id="equalizer"> <div class="eq-bar"></div> <div class="eq-bar"></div> <div class="eq-bar"></div> <div class="eq-bar"></div> </div> </button> <button class="control-btn"> <svg width="24" height="24" fill="none" viewBox="0 0 24 24"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.25 4.75L17.75 12L6.25 19.25V4.75Z"></path> </svg> </button> </div> <div class="volume-container"> <div class="volume-icon"> <svg width="18" height="18" fill="none" viewBox="0 0 24 24"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4.75 12.75H8.25L13.25 17.75V6.25L8.25 11.25H4.75V12.75Z"></path> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17 16.75C18.25 15.25 18.25 12.75 17 11.25"></path> </svg> </div> <div class="volume-slider" id="volumeSlider"> <div class="volume-fill" id="volumeFill"></div> <div class="volume-handle" id="volumeHandle"></div> </div> </div> <button class="playlist-button"> <svg width="18" height="18" fill="none" viewBox="0 0 24 24"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 19.25H17.25"></path> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 15.25H17.25"></path> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 11.25H17.25"></path> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 7.25H17.25"></path> </svg> </button> </div> <script> document.addEventListener('DOMContentLoaded', function() { const playBtn = document.getElementById('playBtn'); const playIcon = document.getElementById('playIcon'); const pauseIcon = document.getElementById('pauseIcon'); const equalizer = document.getElementById('equalizer'); const progressBar = document.getElementById('progressBar'); const progressFill = document.getElementById('progressFill'); const progressHandle = document.getElementById('progressHandle'); const volumeSlider = document.getElementById('volumeSlider'); const volumeFill = document.getElementById('volumeFill'); const volumeHandle = document.getElementById('volumeHandle'); const vibrationContainer = document.getElementById('vibrationContainer'); const soundWaveContainer = document.getElementById('soundWaveContainer'); let isPlaying = false; let isDraggingProgress = false; let isDraggingVolume = false; let activeVibration = null; let bassBeatInterval; // Create sound wave bars const createSoundWaves = () => { soundWaveContainer.innerHTML = ''; const barCount = 40; for (let i = 0; i < barCount; i++) { const bar = document.createElement('div'); bar.className = 'sound-bar'; bar.style.height = '3px'; // Random height when animating const randomHeight = Math.floor(Math.random() * 15) + 5; bar.style.setProperty('--height', `${randomHeight}px`); // Assign random animation duration between 0.5s and 1.2s const animDuration = (Math.random() * 0.7 + 0.5).toFixed(2); // Assign random animation delay const animDelay = (Math.random() * 2).toFixed(2); soundWaveContainer.appendChild(bar); } }; // Initialize sound waves createSoundWaves(); // Animate sound waves const animateSoundWaves = (activate) => { const bars = soundWaveContainer.querySelectorAll('.sound-bar'); bars.forEach(bar => { if (activate) { const randomHeight = Math.floor(Math.random() * 20) + 5; bar.style.setProperty('--height', `${randomHeight}px`); bar.style.animation = `sound-wave ${(Math.random() * 0.7 + 0.5).toFixed(2)}s ease-in-out infinite`; bar.style.animationDelay = `${(Math.random() * 2).toFixed(2)}s`; } else { bar.style.animation = 'none'; bar.style.height = '3px'; } }); }; // Create vibration effect const createVibration = (intensity) => { // Clear any existing vibration clearInterval(activeVibration); if (intensity === 0) return; // Create particles at random positions along the progress bar activeVibration = setInterval(() => { const numParticles = Math.floor(intensity * 3); for (let i = 0; i < numParticles; i++) { const particle = document.createElement('div'); particle.className = 'vibration-particles'; // Random position along the progress bar const position = Math.random() * 100; const barRect = progressBar.getBoundingClientRect(); const containerRect = vibrationContainer.getBoundingClientRect(); const x = (position / 100) * barRect.width; const y = barRect.top - containerRect.top + barRect.height / 2; // Random size and movement const size = Math.random() * 4 + 2; const txDirection = Math.random() > 0.5 ? 1 : -1; const tyDirection = Math.random() > 0.5 ? 1 : -1; const tx = txDirection * (Math.random() * 30 + 10); const ty = tyDirection * (Math.random() * 30 + 10); // Apply styles particle.style.width = `${size}px`; particle.style.height = `${size}px`; particle.style.left = `${x}px`; particle.style.top = `${y}px`; particle.style.setProperty('--tx', `${tx}px`); particle.style.setProperty('--ty', `${ty}px`); vibrationContainer.appendChild(particle); // Remove particle after animation setTimeout(() => { if (particle.parentNode === vibrationContainer) { vibrationContainer.removeChild(particle); } }, 1000); } }, 100); }; // Simulate bass beats that increase vibration const simulateBassBeats = () => { clearInterval(bassBeatInterval); if (!isPlaying) return; let beatCount = 0; let beatPattern = [0.8, 0.2, 0.5, 0.3, 0.7, 0.4]; bassBeatInterval = setInterval(() => { const intensity = beatPattern[beatCount % beatPattern.length]; createVibration(intensity); // Also "wiggle" the progress bar slightly const currentTranslate = (Math.random() * 2 - 1) * intensity; progressBar.style.transform = `translateY(${currentTranslate}px)`; // Reset after small delay setTimeout(() => { progressBar.style.transform = 'translateY(0)'; }, 100); beatCount++; }, 800); }; // Add ripple effect const addRippleEffect = (element, event) => { const rect = element.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; const ripple = document.createElement('span'); ripple.className = 'ripple'; ripple.style.left = `${x}px`; ripple.style.top = `${y}px`; element.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 800); }; // Toggle play/pause playBtn.addEventListener('click', function(e) { isPlaying = !isPlaying; if (isPlaying) { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; equalizer.style.display = 'flex'; animateSoundWaves(true); simulateBassBeats(); } else { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; equalizer.style.display = 'none'; animateSoundWaves(false); clearInterval(activeVibration); clearInterval(bassBeatInterval); } addRippleEffect(this, e); }); // Handle progress bar interaction progressBar.addEventListener('mousedown', function(e) { isDraggingProgress = true; updateProgressPosition(e); }); window.addEventListener('mouseup', function() { isDraggingProgress = false; isDraggingVolume = false; }); window.addEventListener('mousemove', function(e) { if (isDraggingProgress) { updateProgressPosition(e); } if (isDraggingVolume) { updateVolumePosition(e); } }); function updateProgressPosition(e) { const rect = progressBar.getBoundingClientRect(); let position = (e.clientX - rect.left) / rect.width; position = Math.max(0, Math.min(1, position)); const percentage = position * 100; progressFill.style.width = `${percentage}%`; progressHandle.style.left = `${percentage}%`; // Update time display (simulation) const totalSeconds = 303; // 5:03 in seconds const currentTime = Math.floor(position * totalSeconds); const minutes = Math.floor(currentTime / 60); const seconds = currentTime % 60; document.querySelector('.time-current').textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; } // Handle volume slider interaction volumeSlider.addEventListener('mousedown', function(e) { isDraggingVolume = true; updateVolumePosition(e); }); function updateVolumePosition(e) { const rect = volumeSlider.getBoundingClientRect(); let position = (e.clientX - rect.left) / rect.width; position = Math.max(0, Math.min(1, position)); const percentage = position * 100; volumeFill.style.width = `${percentage}%`; volumeHandle.style.left = `${percentage}%`; } // Add interaction for all buttons document.querySelectorAll('.control-btn, .playlist-button').forEach(btn => { btn.addEventListener('click', function(e) { addRippleEffect(this, e); }); }); // Simulate an interactive element that responds to hover const trackTitle = document.querySelector('.track-title'); trackTitle.addEventListener('mouseover', function() { this.style.color = 'var(--primary-color)'; }); trackTitle.addEventListener('mouseout', function() { this.style.color = ''; }); // Initialize the equalizer bars const eqBars = equalizer.querySelectorAll('.eq-bar'); eqBars.forEach((bar, index) => { const height = Math.floor(Math.random() * 10) + 5; bar.style.height = `${height}px`; const animDuration = (Math.random() * 0.4 + 0.3).toFixed(2); bar.style.animation = `sound-wave ${animDuration}s ease-in-out infinite`; bar.style.animationDelay = `${(index * 0.1).toFixed(2)}s`; }); // Add touch support for mobile progressBar.addEventListener('touchstart', function(e) { isDraggingProgress = true; updateProgressTouch(e); }); volumeSlider.addEventListener('touchstart', function(e) { isDraggingVolume = true; updateVolumeTouch(e); }); window.addEventListener('touchend', function() { isDraggingProgress = false; isDraggingVolume = false; }); window.addEventListener('touchmove', function(e) { if (isDraggingProgress) { updateProgressTouch(e); } if (isDraggingVolume) { updateVolumeTouch(e); } }); function updateProgressTouch(e) { const touch = e.touches[0] || e.changedTouches[0]; const rect = progressBar.getBoundingClientRect(); let position = (touch.clientX - rect.left) / rect.width; position = Math.max(0, Math.min(1, position)); const percentage = position * 100; progressFill.style.width = `${percentage}%`; progressHandle.style.left = `${percentage}%`; // Update time display const totalSeconds = 303; // 5:03 in seconds const currentTime = Math.floor(position * totalSeconds); const minutes = Math.floor(currentTime / 60); const seconds = currentTime % 60; document.querySelector('.time-current').textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; } function updateVolumeTouch(e) { const touch = e.touches[0] || e.changedTouches[0]; const rect = volumeSlider.getBoundingClientRect(); let position = (touch.clientX - rect.left) / rect.width; position = Math.max(0, Math.min(1, position)); const percentage = position * 100; volumeFill.style.width = `${percentage}%`; volumeHandle.style.left = `${percentage}%`; } // Prevent default on any form elements to avoid page refresh document.querySelectorAll('button, input').forEach(el => { el.addEventListener('click', e => e.preventDefault()); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AccessBeats Music Player</title> <style> :root { --primary: #0066CC; --primary-dark: #0052a3; --secondary: #FF6B00; --background: #FFFFFF; --text-dark: #000000; --text-light: #FFFFFF; --border-radius: 16px; --shadow: 0 6px 12px rgba(0, 0, 0, 0.1); --focus-ring: 0 0 0 3px rgba(0, 102, 204, 0.5); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--background); color: var(--text-dark); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; } .player-container { width: 100%; max-width: 660px; background-color: var(--background); border-radius: var(--border-radius); box-shadow: var(--shadow); padding: 32px; display: flex; flex-direction: column; position: relative; overflow: hidden; gap: 24px; } .welcome-message { display: flex; flex-direction: column; gap: 16px; text-align: center; margin-bottom: 12px; } .welcome-message h1 { font-size: 32px; font-weight: 700; color: var(--primary); } .welcome-message p { font-size: 18px; line-height: 1.5; } .now-playing { display: flex; flex-direction: column; align-items: center; gap: 16px; } .album-art { width: 190px; height: 190px; border-radius: var(--border-radius); border: 3px solid var(--primary); overflow: hidden; position: relative; box-shadow: var(--shadow); transition: transform 0.3s, box-shadow 0.3s; } .album-art img { width: 100%; height: 100%; object-fit: cover; } .album-art::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(45deg, rgba(0, 102, 204, 0.2), rgba(255, 107, 0, 0.2)); z-index: 1; } .track-info { text-align: center; width: 100%; } .track-title { font-size: 24px; font-weight: 700; margin-bottom: 8px; } .artist-name { font-size: 18px; color: #666; margin-bottom: 16px; } .progress-container { width: 100%; background-color: #EEEEEE; border-radius: 24px; height: 16px; position: relative; margin-bottom: 8px; box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); } .progress-bar { width: 40%; background: linear-gradient(to right, var(--primary), var(--secondary)); border-radius: 24px; height: 100%; position: relative; } .progress-handle { position: absolute; right: -12px; top: 50%; transform: translateY(-50%); width: 24px; height: 24px; background-color: var(--text-light); border: 3px solid var(--primary); border-radius: 50%; cursor: pointer; transition: transform 0.2s; } .progress-handle:hover, .progress-handle:focus { transform: translateY(-50%) scale(1.2); } .time-display { display: flex; justify-content: space-between; font-size: 16px; font-weight: 600; } .controls { display: flex; justify-content: center; gap: 20px; width: 100%; margin-top: 16px; } .control-btn { width: 66px; height: 66px; border-radius: 50%; border: none; background-color: var(--primary); color: var(--text-light); font-size: 24px; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.2s; position: relative; } .control-btn.play-pause { width: 76px; height: 76px; background-color: var(--secondary); } .control-btn:hover, .control-btn:focus { transform: scale(1.1); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); } .control-btn:active { transform: scale(0.95); } .control-btn:focus { outline: none; box-shadow: var(--focus-ring); } .control-btn svg { width: 32px; height: 32px; } .control-btn.play-pause svg { width: 40px; height: 40px; } .volume-container { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 16px; width: 100%; } .volume-icon { font-size: 24px; color: var(--primary); } .volume-slider { width: 70%; height: 16px; -webkit-appearance: none; appearance: none; background-color: #EEEEEE; border-radius: 24px; outline: none; box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; border-radius: 50%; background-color: var(--text-light); border: 3px solid var(--primary); cursor: pointer; transition: transform 0.2s; } .volume-slider::-moz-range-thumb { width: 24px; height: 24px; border-radius: 50%; background-color: var(--text-light); border: 3px solid var(--primary); cursor: pointer; transition: transform 0.2s; } .volume-slider::-webkit-slider-thumb:hover { transform: scale(1.2); } .volume-slider::-moz-range-thumb:hover { transform: scale(1.2); } .playlist { width: 100%; padding: 16px; background-color: #F7F7F7; border-radius: var(--border-radius); margin-top: 16px; } .playlist-title { font-size: 20px; margin-bottom: 16px; color: var(--primary); font-weight: 700; } .playlist-item { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: 8px; background-color: var(--background); cursor: pointer; transition: background-color 0.2s; margin-bottom: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .playlist-item:hover, .playlist-item.active { background-color: rgba(0, 102, 204, 0.1); } .playlist-item.active { font-weight: 700; border-left: 4px solid var(--secondary); padding-left: 8px; } .playlist-item img { width: 48px; height: 48px; border-radius: 8px; object-fit: cover; } .playlist-info { flex: 1; } .playlist-track { font-size: 16px; font-weight: 600; } .playlist-artist { font-size: 14px; color: #666; } .playlist-duration { font-size: 14px; font-weight: 600; color: var(--primary); } .accessibility-menu { position: absolute; top: 16px; right: 16px; display: flex; gap: 8px; } .accessibility-btn { width: 40px; height: 40px; border-radius: 8px; border: 2px solid var(--primary); background-color: var(--background); color: var(--primary); font-size: 16px; cursor: pointer; display: flex; justify-content: center; align-items: center; transition: all 0.2s; } .accessibility-btn:hover, .accessibility-btn:focus { background-color: var(--primary); color: var(--text-light); } .high-contrast .player-container { background-color: #000000; color: #FFFFFF; } .high-contrast .welcome-message h1 { color: #FFFF00; } .high-contrast .album-art { border-color: #FFFF00; } .high-contrast .control-btn { background-color: #FFFF00; color: #000000; } .high-contrast .control-btn.play-pause { background-color: #FF0000; } .high-contrast .progress-bar { background: #FFFF00; } .high-contrast .progress-handle { background-color: #000000; border-color: #FFFF00; } .high-contrast .playlist { background-color: #333333; } .high-contrast .playlist-item { background-color: #000000; color: #FFFFFF; } .high-contrast .playlist-item:hover, .high-contrast .playlist-item.active { background-color: #444444; } .high-contrast .playlist-item.active { border-left-color: #FF0000; } .larger-text .welcome-message h1 { font-size: 36px; } .larger-text .welcome-message p, .larger-text .track-title { font-size: 28px; } .larger-text .artist-name { font-size: 22px; } .larger-text .time-display, .larger-text .playlist-track { font-size: 20px; } .larger-text .playlist-artist, .larger-text .playlist-duration { font-size: 18px; } .pulse-animation .control-btn.play-pause { animation: pulse 1.5s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 107, 0, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(255, 107, 0, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 107, 0, 0); } } .skip-animation { animation: skipAnim 0.5s; } @keyframes skipAnim { 0% { transform: translateX(0); } 25% { transform: translateX(15px); } 50% { transform: translateX(0); } 75% { transform: translateX(15px); } 100% { transform: translateX(0); } } .prev-animation { animation: prevAnim 0.5s; } @keyframes prevAnim { 0% { transform: translateX(0); } 25% { transform: translateX(-15px); } 50% { transform: translateX(0); } 75% { transform: translateX(-15px); } 100% { transform: translateX(0); } } /* Auditory guidance simulation */ .audio-guide { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background-color: var(--primary); color: var(--text-light); padding: 12px 20px; border-radius: 30px; font-size: 16px; opacity: 0; transition: opacity 0.3s, transform 0.3s; pointer-events: none; z-index: 100; max-width: 80%; text-align: center; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .audio-guide.visible { opacity: 1; transform: translateX(-50%) translateY(-10px); } @media (max-width: 680px) { .player-container { padding: 24px 16px; } .album-art { width: 150px; height: 150px; } .controls { gap: 12px; } .control-btn { width: 54px; height: 54px; } .control-btn.play-pause { width: 64px; height: 64px; } .welcome-message h1 { font-size: 28px; } .track-title { font-size: 20px; } } @media (max-width: 480px) { .controls { gap: 8px; } .control-btn { width: 48px; height: 48px; } .control-btn.play-pause { width: 56px; height: 56px; } .album-art { width: 120px; height: 120px; } } </style> </head> <body> <div class="player-container" id="player"> <div class="welcome-message"> <h1>AccessBeats</h1> <p>A music player designed for everyone, with enhanced accessibility features</p> </div> <div class="now-playing"> <div class="album-art"> <img src="https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=600&auto=format&fit=crop" alt="Album artwork for Rhythm in Motion by The Soundscapes"> </div> <div class="track-info"> <div class="track-title">Rhythm in Motion</div> <div class="artist-name">The Soundscapes</div> <div class="progress-container" id="progress-container"> <div class="progress-bar" id="progress-bar"> <div class="progress-handle" id="progress-handle" tabindex="0" aria-label="Seek song position"></div> </div> </div> <div class="time-display"> <div class="current-time">1:54</div> <div class="total-time">4:32</div> </div> </div> </div> <div class="controls"> <button class="control-btn previous" aria-label="Previous track"> <svg viewBox="0 0 24 24" fill="currentColor"> <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/> </svg> </button> <button class="control-btn play-pause" aria-label="Play or pause"> <svg viewBox="0 0 24 24" fill="currentColor" id="play-icon"> <path d="M8 5v14l11-7z"/> </svg> <svg viewBox="0 0 24 24" fill="currentColor" id="pause-icon" style="display:none;"> <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> </svg> </button> <button class="control-btn next" aria-label="Next track"> <svg viewBox="0 0 24 24" fill="currentColor"> <path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/> </svg> </button> </div> <div class="volume-container"> <div class="volume-icon"> <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24"> <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/> </svg> </div> <input type="range" min="0" max="100" value="80" class="volume-slider" id="volume-slider" aria-label="Volume"> </div> <div class="playlist"> <div class="playlist-title">Up Next</div> <div class="playlist-item active"> <img src="https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=600&auto=format&fit=crop" alt="Thumbnail for Rhythm in Motion"> <div class="playlist-info"> <div class="playlist-track">Rhythm in Motion</div> <div class="playlist-artist">The Soundscapes</div> </div> <div class="playlist-duration">4:32</div> </div> <div class="playlist-item"> <img src="https://images.unsplash.com/photo-1511379938547-c1f69419868d?w=600&auto=format&fit=crop" alt="Thumbnail for Calm Waters"> <div class="playlist-info"> <div class="playlist-track">Calm Waters</div> <div class="playlist-artist">Ocean Echoes</div> </div> <div class="playlist-duration">3:28</div> </div> <div class="playlist-item"> <img src="https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=600&auto=format&fit=crop" alt="Thumbnail for Urban Beats"> <div class="playlist-info"> <div class="playlist-track">Urban Beats</div> <div class="playlist-artist">City Pulse</div> </div> <div class="playlist-duration">5:12</div> </div> </div> <div class="accessibility-menu"> <button class="accessibility-btn" id="contrast-toggle" aria-label="Toggle high contrast mode"> <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/> <path d="M12 4v16c4.41 0 8-3.59 8-8s-3.59-8-8-8z"/> </svg> </button> <button class="accessibility-btn" id="text-size-toggle" aria-label="Toggle larger text"> <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24"> <path d="M2.5 4v3h5v12h3V7h5V4h-13zm19 5h-9v3h3v7h3v-7h3V9z"/> </svg> </button> </div> </div> <div class="audio-guide" id="audio-guide"></div> <script> // DOM elements const player = document.getElementById('player'); const playPauseBtn = document.querySelector('.play-pause'); const prevBtn = document.querySelector('.previous'); const nextBtn = document.querySelector('.next'); const progressBar = document.getElementById('progress-bar'); const progressHandle = document.getElementById('progress-handle'); const progressContainer = document.getElementById('progress-container'); const volumeSlider = document.getElementById('volume-slider'); const contrastToggle = document.getElementById('contrast-toggle'); const textSizeToggle = document.getElementById('text-size-toggle'); const audioGuide = document.getElementById('audio-guide'); const playIcon = document.getElementById('play-icon'); const pauseIcon = document.getElementById('pause-icon'); const playlistItems = document.querySelectorAll('.playlist-item'); // State let isPlaying = false; let isDragging = false; let currentVolume = 80; let currentTrackIndex = 0; // Track data const tracks = [ { title: "Rhythm in Motion", artist: "The Soundscapes", duration: "4:32", image: "https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=600&auto=format&fit=crop" }, { title: "Calm Waters", artist: "Ocean Echoes", duration: "3:28", image: "https://images.unsplash.com/photo-1511379938547-c1f69419868d?w=600&auto=format&fit=crop" }, { title: "Urban Beats", artist: "City Pulse", duration: "5:12", image: "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=600&auto=format&fit=crop" } ]; // Event listeners playPauseBtn.addEventListener('click', togglePlayPause); prevBtn.addEventListener('click', playPrevious); nextBtn.addEventListener('click', playNext); progressContainer.addEventListener('click', seek); progressHandle.addEventListener('mousedown', startDrag); volumeSlider.addEventListener('input', changeVolume); contrastToggle.addEventListener('click', toggleContrast); textSizeToggle.addEventListener('click', toggleTextSize); // Add event listeners to playlist items playlistItems.forEach((item, index) => { item.addEventListener('click', () => { changeTrack(index); }); }); // Keyboard navigation document.addEventListener('keydown', (e) => { if (e.code === 'Space') { e.preventDefault(); togglePlayPause(); } else if (e.code === 'ArrowRight') { playNext(); } else if (e.code === 'ArrowLeft') { playPrevious(); } else if (e.code === 'ArrowUp') { volumeSlider.value = Math.min(parseInt(volumeSlider.value) + 10, 100); changeVolume(); } else if (e.code === 'ArrowDown') { volumeSlider.value = Math.max(parseInt(volumeSlider.value) - 10, 0); changeVolume(); } }); // Handle progress bar drag events document.addEventListener('mousemove', (e) => { if (isDragging) { const rect = progressContainer.getBoundingClientRect(); const pos = (e.clientX - rect.left) / rect.width; updateProgressPosition(pos); } }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; } }); // Functions function togglePlayPause() { isPlaying = !isPlaying; if (isPlaying) { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; player.classList.add('pulse-animation'); showAudioGuide(`Now playing: ${tracks[currentTrackIndex].title} by ${tracks[currentTrackIndex].artist}`); } else { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; player.classList.remove('pulse-animation'); showAudioGuide('Paused'); } // Simulate progress moving when playing if (isPlaying) { progressInterval = setInterval(() => { const width = parseFloat(getComputedStyle(progressBar).width); const containerWidth = parseFloat(getComputedStyle(progressContainer).width); let newWidth = width + 1; if (newWidth >= containerWidth) { clearInterval(progressInterval); playNext(); } else { progressBar.style.width = `${(newWidth / containerWidth) * 100}%`; updateCurrentTime(); } }, 1000); } else { clearInterval(progressInterval); } } function playNext() { currentTrackIndex = (currentTrackIndex + 1) % tracks.length; changeTrack(currentTrackIndex); // Add animation effect const albumArt = document.querySelector('.album-art'); albumArt.classList.add('skip-animation'); setTimeout(() => { albumArt.classList.remove('skip-animation'); }, 500); } function playPrevious() { currentTrackIndex = (currentTrackIndex - 1 + tracks.length) % tracks.length; changeTrack(currentTrackIndex); // Add animation effect const albumArt = document.querySelector('.album-art'); albumArt.classList.add('prev-animation'); setTimeout(() => { albumArt.classList.remove('prev-animation'); }, 500); } function changeTrack(index) { currentTrackIndex = index; // Update track information document.querySelector('.track-title').textContent = tracks[index].title; document.querySelector('.artist-name').textContent = tracks[index].artist; document.querySelector('.album-art img').src = tracks[index].image; document.querySelector('.album-art img').alt = `Album artwork for ${tracks[index].title} by ${tracks[index].artist}`; document.querySelector('.total-time').textContent = tracks[index].duration; // Reset progress progressBar.style.width = '0%'; document.querySelector('.current-time').textContent = '0:00'; // Update playlist active state playlistItems.forEach((item, i) => { if (i === index) { item.classList.add('active'); } else { item.classList.remove('active'); } }); // Auto-play the track if we were already playing if (isPlaying) { // If we were playing, restart the interval clearInterval(progressInterval); // Start a little into the song to show progress progressBar.style.width = '5%'; updateCurrentTime(); progressInterval = setInterval(() => { const width = parseFloat(getComputedStyle(progressBar).width); const containerWidth = parseFloat(getComputedStyle(progressContainer).width); let newWidth = width + 1; if (newWidth >= containerWidth) { clearInterval(progressInterval); playNext(); } else { progressBar.style.width = `${(newWidth / containerWidth) * 100}%`; updateCurrentTime(); } }, 1000); } showAudioGuide(`Changed to: ${tracks[index].title} by ${tracks[index].artist}`); } function seek(e) { const rect = progressContainer.getBoundingClientRect(); const pos = (e.clientX - rect.left) / rect.width; updateProgressPosition(pos); // If we're playing, restart the progress simulation from the new position if (isPlaying) { clearInterval(progressInterval); progressInterval = setInterval(() => { const width = parseFloat(getComputedStyle(progressBar).width); const containerWidth = parseFloat(getComputedStyle(progressContainer).width); let newWidth = width + 1; if (newWidth >= containerWidth) { clearInterval(progressInterval); playNext(); } else { progressBar.style.width = `${(newWidth / containerWidth) * 100}%`; updateCurrentTime(); } }, 1000); } showAudioGuide('Seeking to ' + document.querySelector('.current-time').textContent); } function startDrag() { isDragging = true; } function updateProgressPosition(pos) { // Ensure position is between 0 and 1 pos = Math.max(0, Math.min(1, pos)); // Update progress bar width progressBar.style.width = `${pos * 100}%`; // Update current time updateCurrentTime(); } function updateCurrentTime() { const width = parseFloat(getComputedStyle(progressBar).width); const containerWidth = parseFloat(getComputedStyle(progressContainer).width); const pos = width / containerWidth; // Get total seconds from duration (e.g., "4:32" -> 272 seconds) const durationParts = tracks[currentTrackIndex].duration.split(':'); const totalSeconds = parseInt(durationParts[0]) * 60 + parseInt(durationParts[1]); // Calculate current seconds based on position const currentSeconds = Math.floor(pos * totalSeconds); const minutes = Math.floor(currentSeconds / 60); const seconds = currentSeconds % 60; // Update current time display document.querySelector('.current-time').textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; } function changeVolume() { currentVolume = volumeSlider.value; showAudioGuide(`Volume set to ${currentVolume}%`); } function toggleContrast() { document.body.classList.toggle('high-contrast'); if (document.body.classList.contains('high-contrast')) { showAudioGuide('High contrast mode enabled'); } else { showAudioGuide('Standard contrast mode enabled'); } } function toggleTextSize() { document.body.classList.toggle('larger-text'); if (document.body.classList.contains('larger-text')) { showAudioGuide('Larger text mode enabled'); } else { showAudioGuide('Standard text size enabled'); } } function showAudioGuide(message) { audioGuide.textContent = message; audioGuide.classList.add('visible'); // Hide after 3 seconds setTimeout(() => { audioGuide.classList.remove('visible'); }, 3000); } // Initialize to show we're in a paused state with a track loaded updateCurrentTime(); </script> </body> </html>