티스토리 뷰
Toy Projects/JavaScript - Mp3 플레이어
JavaScript- mp3 Player 구현 / 자바스크립트 - mp3 Player 구현
하눤석 2022. 4. 12. 16:14728x90
mp3 플레이어
유튜브 API를 받아와 영상을 재생해주는 웹 서비스 개발을 구상하고 있습니다. 영상을 재생하기 위한 플레이어를 구현해 보았습니다.
주요 기능
- 음악 재생
플레이 버튼 클릭 시, 음악이 재생되고 음악의 총 재생시간과 현재 재생시간을 게이지바로 나타내었습니다.
- 정지 버튼
음악 플레이 중에는 재생 버튼이 일시정지 버튼으로 바뀌고 이 버튼을 클릭할 시 음악이 일시 정지되게 하였습니다.
- 음악 변경
좌, 우 버튼 클릭시 다음 노래 또는 이전 노래를 선택할 수 있게 구현하였습니다.
- 현재 노래 반복, 랜덤 셔플
현재 노래 반복과 랜덤 셔플 기능을 추가하여 해당 기능을 선택 시 기능에 맞게 현재 음악이 반복재생되거나 다음 노래를 선택할 때 자동 셔플되도록 하였습니다.
- 플레이리스트
플레이리스트 버튼을 추가하여 좌, 우 버튼이 아닌 직접 플레이리스트에서 노래를 선택하여 재생할 수 있도록 하였습니다.
소스 코드
전체 소스는 https://github.com/wonseok22/ToyProjects/tree/main/musicPlayer 를 참고하세요.
const musicWrap = document.querySelector(".wrap__music");
const musicImg = musicWrap.querySelector(".music__img img");
const musicName = musicWrap.querySelector(".music__song .name");
const musicArtist = musicWrap.querySelector(".music__song .artist");
const musicAudio = musicWrap.querySelector("#main-audio");
const musicPlay = musicWrap.querySelector("#control-play");
const musicPrevBtn = musicWrap.querySelector("#control-prev");
const musicNextBtn = musicWrap.querySelector("#control-next");
const musicProgress = musicWrap.querySelector(".music__progress");
const musicProgressBar = musicProgress.querySelector(".bar");
const musicProgressCurrent = musicProgress.querySelector(".current");
const musicProgressDuration = musicProgress.querySelector(".duration");
const musicRepeat = musicWrap.querySelector("#control-repeat");
const musicList = musicWrap.querySelector(".music__list");
const MusicListBtn = musicWrap.querySelector("#control-list");
const MusicListClose = musicList.querySelector(".close");
const musicListUl = musicList.querySelector(".list ul");
let musicIndex = 1;
// 음악 재생
function loadMusic(num){
musicImg.src = `images/${allMusic[num - 1].img}.jpg`;
musicImg.alt = `${allMusic[num - 1].img}`;
musicName.innerText = allMusic[num - 1].name;
musicArtist.innerText = allMusic[num - 1].artist;
musicAudio.src = `songs/${allMusic[num - 1].audio}.mp3`;
}
// 플레이 버튼
function playMusic(){
musicWrap.classList.add("paused");
musicPlay.innerText = "pause";
musicPlay.setAttribute("title", "일시정지")
musicAudio.play();
}
// 일시정지 버튼
function pauseMusic(){
musicWrap.classList.remove("paused");
musicPlay.innerText = "play_arrow";
musicPlay.setAttribute("title", "재생")
musicAudio.pause();
}
// 이전 곡 듣기 버튼
function prevMusic(){
musicIndex--;
musicIndex < 1 ? musicIndex = allMusic.length : musicIndex = musicIndex;
loadMusic(musicIndex);
playMusic();
playListMusic();
}
// 다음 곡 듣기 버튼
function nextMusic(){
musicIndex++;
musicIndex > allMusic.length ? musicIndex = 1 : musicIndex = musicIndex;
loadMusic(musicIndex);
playMusic();
playListMusic();
}
// 뮤직 진행바
musicAudio.addEventListener("timeupdate", (e)=>{
const currentTime = e.target.currentTime;
const duration = e.target.duration;
let progressWidth = (currentTime/duration) * 100;
musicProgressBar.style.width = `${progressWidth}%`
musicAudio.addEventListener("loadeddata", ()=>{
let audioDuration = musicAudio.duration;
let totalMin = Math.floor(audioDuration / 60);
let totalSec = Math.floor(audioDuration % 60);
if (totalSec < 10) totalSec = `0${totalSec}`;
musicProgressDuration.innerText = `${totalMin}:${totalSec}`;
})
let currentMin = Math.floor(currentTime / 60);
let currentSec = Math.floor(currentTime % 60);
if (currentSec < 10) currentSec = `0${currentSec}`;
musicProgressCurrent.innerText = `${currentMin}:${currentSec}`
})
// 진행 버튼
musicProgress.addEventListener("click", e=>{
let progressWidth = musicProgress.clientWidth;
let clickedOffsetX = e.offsetX;
let songDuration = musicAudio.duration;
musicAudio.currentTime = (clickedOffsetX / progressWidth) * songDuration;
playMusic();
})
// 재생/일시정지
musicPlay.addEventListener("click", ()=>{
const isMusicPaused = musicWrap.classList.contains("paused");
isMusicPaused ? pauseMusic() : playMusic();
})
musicPrevBtn.addEventListener("click", ()=>{
prevMusic();
});
musicNextBtn.addEventListener("click", ()=>{
nextMusic();
});
// 반복 버튼
musicRepeat.addEventListener("click", ()=>{
let getText = musicRepeat.innerText;
switch(getText){
case "repeat" :
musicRepeat.innerText = "repeat_one";
musicRepeat.setAttribute("title", "한곡 반복")
break;
case "repeat_one" :
musicRepeat.innerText = "shuffle";
musicRepeat.setAttribute("title", "랜덤 반복")
break;
case "shuffle" :
musicRepeat.innerText = "repeat";
musicRepeat.setAttribute("title", "전체 반복")
playListMusic();
break;
}
})
// 오디오가 끝나고
musicAudio.addEventListener("ended", ()=>{
let getText = musicRepeat.innerText;
switch(getText){
case "repeat" :
nextMusic();
break;
case "repeat_one" :
loadMusic(musicIndex);
playMusic();
break;
case "shuffle" :
let randIndex = Math.floor((Math.random() * allMusic.length) + 1);
do {
randIndex = Math.floor((Math.random() * allMusic.length) + 1);
} while (musicIndex == randIndex);
musicIndex = randIndex;
loadMusic(musicIndex);
playMusic();
break;
}
})
// 뮤직 리스트 버튼
MusicListBtn.addEventListener("click", ()=>{
musicList.classList.add("show");
})
// 뮤직 리스트 닫기 버튼
MusicListClose.addEventListener("click", ()=>{
musicList.classList.remove("show");
})
// 뮤직 리스트 구현하기
for(let i=0; i<allMusic.length; i++){
let li = `
<li data-index="${i + 1}">
<div>
<em>${allMusic[i].name}</em>
<p>${allMusic[i].artist}</p>
</div>
<audio class="${allMusic[i].audio}" src="songs/${allMusic[i].audio}.mp3"></audio>
<span id="${allMusic[i].audio}" class="audio-duration">3:36</span>
</li>
`;
musicListUl.insertAdjacentHTML("beforeend", li);
let liAudioDuration = musicListUl.querySelector(`#${allMusic[i].audio}`);
let liAudio = musicListUl.querySelector(`.${allMusic[i].audio}`);
liAudio.addEventListener("loadeddata", () => {
let audioDuration = liAudio.duration;
let totalMin = Math.floor(audioDuration / 60);
let totalSec = Math.floor(audioDuration % 60);
if (totalSec < 10) totalSec = `0${totalSec}`;
liAudioDuration.innerText = `${totalMin}:${totalSec}`;
liAudioDuration.setAttribute("data-duration", `${totalMin}:${totalSec}`);
});
}
// 뮤직 리스트 클릭하기
const musicListAll = musicListUl.querySelectorAll("li");
function playListMusic(){
for(let j=0; j<musicListAll.length; j++){
let audioTag = musicListAll[j].querySelector(".audio-duration");
let adDuration = audioTag.getAttribute("data-duration");
if(musicListAll[j].classList.contains("playing")){
musicListAll[j].classList.remove("playing");
audioTag.innerText = adDuration;
}
if(musicListAll[j].getAttribute("data-index") == musicIndex){
musicListAll[j].classList.add("playing");
audioTag.innerText = "재생중";
}
musicListAll[j].setAttribute("onclick", "clicked(this)");
}
}
function clicked(el){
let getLiIndex = el.getAttribute("data-index");
musicIndex = getLiIndex;
loadMusic(musicIndex);
playMusic();
playListMusic();
}
// 창이 열리면 노래 시작
window.addEventListener("load", ()=>{
loadMusic(musicIndex);
playListMusic();
});
320x100
댓글
© 2022 WonSeok, All rights reserved