const MusicPlayer = () => {
const [currTrack, setCurrTrack] = useState(0);
const { play, stop, sound, pause } = useSound(
tracks[currTrack].soundSrc);
const [isPlaying, setIsPlaying] = useState(false);
const [pos, setPos] = useState(0);
// regularly update the progress bar
useEffect(() => {
if (isPlaying) {
const intervalId = setInterval(() => {
if (sound?.seek() >= sound?.duration() - 0.5) {
sound?.seek(0);
} else setPos(sound?.seek());
}, 1);
return () => clearInterval(intervalId);
}
}, [isPlaying, sound]);
// seek a position on thre track based on click
const seek = (newVal) => {
sound?.seek((newVal / 100) * sound?.duration());
if (!isPlaying) {
setIsPlaying(true);
}
};
const changeTrack = (diff) => {
// no more tracks to go to
if (currTrack + diff < 0 || currTrack + diff >= tracks.length) {
// restart the current track
sound?.seek(0);
return;
}
setCurrTrack(currTrack + diff);
};
useEffect(() => {
if (isPlaying) {
play();
} else {
pause();
}
}, [play, pause, isPlaying]);
// stop sound when leaving the page
useEffect(() => {
return () => {
stop();
};
}, [stop]);
return (
<PlayerWrapper>
<CoverArt src={tracks[currTrack].imgSrc} />
<SongTitle>{tracks[currTrack].title}</SongTitle>
<SongArtist>{tracks[currTrack].artist}</SongArtist>
<ProgressSlider
value={(pos / sound?.duration()) * 100}
seek={seek} />
<TrackControls>
<PrevTrackBtn onClick={() => changeTrack(-1)}/>
<PlayBtn>
{isPlaying ? (
<BsPauseCircleFill onClick={() => {setIsPlaying(false);}}/>
) : (
<BsPlayCircleFill onClick={() => {setIsPlaying(true);}}/>
)}
</PlayBtn>
<NextTrackBtn onClick={() => changeTrack(1)}/>
</TrackControls>
</PlayerWrapper>
);
};
const tracks = [
{
title: "Order",
artist: "ComaStudio",
imgSrc: orderCoverArt,
soundSrc: orderSong,
},
{
title: "Abstract Design",
artist: "ComaStudio",
imgSrc: adCoverArt,
soundSrc: adSong,
},
{
title: "Lucid",
artist: "Nomyn",
imgSrc: lucidCoverArt,
soundSrc: lucidSong,
},
];
Note: Code snippets do not include styling details unless they are the focus of the exercise.
Copyright © 2022 Explore React