retrospace-blastoff / script.js
mrdreamers's picture
Manual changes saved
93b8c11 verified
// Simple MySpace-style music player with fake EQ bars
document.addEventListener("DOMContentLoaded", () => {
// === PLAYLIST ===
const playlist = [
{
title: "The Ocean",
artist: "Super Fuzz",
src: "https://cdn-uploads.huggingface.co/production/uploads/693f06e4c231c8267144eb68/WwdKDnPZAW9q7tXWomfSY.mpga",
},
];
// === GRAB ELEMENTS FROM THE PAGE ===
const audioEl = document.getElementById("audio-player");
const titleEl = document.getElementById("track-title");
const artistEl = document.getElementById("track-artist");
const playPauseBtn = document.getElementById("play-pause-btn");
const prevBtn = document.getElementById("prev-btn");
const nextBtn = document.getElementById("next-btn");
const seekBar = document.getElementById("seek-bar");
const eqBars = document.querySelectorAll(".eq-visualizer .eq-bar");
// Safety check – if something's missing, don't crash
if (
!audioEl ||
!titleEl ||
!artistEl ||
!playPauseBtn ||
!prevBtn ||
!nextBtn ||
!seekBar
) {
console.warn("Music player: required elements not found.");
return;
}
let currentTrackIndex = 0;
let isPlaying = false;
let isSeeking = false;
let eqInterval = null;
// === EQ BAR ANIMATION (FAKE VISUALIZER) ===
function startEq() {
if (!eqBars.length || eqInterval) return;
eqInterval = setInterval(() => {
eqBars.forEach((bar) => {
const height = 20 + Math.random() * 80; // 20%–100%
bar.style.height = `${height}%`;
});
}, 120);
}
function stopEq() {
if (eqInterval) {
clearInterval(eqInterval);
eqInterval = null;
}
eqBars.forEach((bar) => {
bar.style.height = "25%"; // idle height
});
}
// === CORE FUNCTIONS ===
function loadTrack(index) {
const track = playlist[index];
if (!track) return;
titleEl.textContent = track.title;
artistEl.textContent = track.artist;
audioEl.src = track.src;
}
function playTrack() {
if (!audioEl.src) {
// just in case loadTrack didn't run for some reason
loadTrack(currentTrackIndex);
}
const playPromise = audioEl.play();
if (playPromise !== undefined) {
playPromise
.then(() => {
isPlaying = true;
playPauseBtn.textContent = "⏸"; // pause icon
startEq();
})
.catch((err) => {
console.warn("Autoplay/play blocked or failed:", err);
});
}
}
function pauseTrack() {
audioEl.pause();
isPlaying = false;
playPauseBtn.textContent = "▶"; // play icon
stopEq();
}
function togglePlay() {
if (isPlaying) {
pauseTrack();
} else {
playTrack();
}
}
function playNext() {
currentTrackIndex = (currentTrackIndex + 1) % playlist.length;
loadTrack(currentTrackIndex);
playTrack();
}
function playPrev() {
currentTrackIndex =
(currentTrackIndex - 1 + playlist.length) % playlist.length;
loadTrack(currentTrackIndex);
playTrack();
}
// === EVENT LISTENERS ===
// Play / Pause button
playPauseBtn.addEventListener("click", togglePlay);
// Next / Previous
nextBtn.addEventListener("click", playNext);
prevBtn.addEventListener("click", playPrev);
// Keep seek bar in sync with audio
audioEl.addEventListener("timeupdate", () => {
if (!audioEl.duration || isSeeking) return;
const progress = (audioEl.currentTime / audioEl.duration) * 100;
seekBar.value = progress;
});
// Scrub / seek when user drags the slider
seekBar.addEventListener("input", () => {
if (!audioEl.duration) return;
isSeeking = true;
const newTime = (seekBar.value / 100) * audioEl.duration;
audioEl.currentTime = newTime;
});
seekBar.addEventListener("change", () => {
isSeeking = false;
});
// When a track ends, loop playlist
audioEl.addEventListener("ended", () => {
playNext();
});
// If there's an audio error (bad URL, etc.)
audioEl.addEventListener("error", (e) => {
console.warn("Audio element error:", e);
});
// === INITIALIZE ===
// Load first track
loadTrack(currentTrackIndex);
// Try autoplay on load (browser may block this until user clicks)
playTrack();
});