완성된 사이트 입니다.
const allMusic = [
{
name :"1. 마마마마",
artist : "Easda sas",
img : "music_view01",
audio : "music_audio01"
},{
name :"2. 마마마마",
artist : "Easda sas",
img : "music_view02",
audio : "music_audio02"
},{
name :"3. 마마마마",
artist : "Easda sas",
img : "music_view03",
audio : "music_audio03"
},{
name :"4. 마마마마",
artist : "Easda sas",
img : "music_view04",
audio : "music_audio04"
},{
name :"5. 마마마마",
artist : "Easda sas",
img : "music_view05",
audio : "music_audio05"
},{
name :"6. 마마마마",
artist : "Easda sas",
img : "music_view06",
audio : "music_audio06"
},{
name :"7. 마마마마",
artist : "Easda sas",
img : "music_view07",
audio : "music_audio07"
},{
name :"8. 마마마마",
artist : "Easda sas",
img : "music_view08",
audio : "music_audio08"
},{
name :"9. 마마마마",
artist : "Easda sas",
img : "music_view09",
audio : "music_audio09"
},{
name :"10. 마마마마",
artist : "Easda sas",
img : "music_view10",
audio : "music_audio10"
}
];
음악 정보를 배열로 저장하였습니다.
const musicWrap = document.querySelector(".music__wrap");
const musicName = musicWrap.querySelector(".music__control .title h3");
const musicArtist = musicWrap.querySelector(".music__control .title p");
const musicView = musicWrap.querySelector(".music__view .image img");
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(".progress");
const musicProgressBar = musicWrap.querySelector(".progress .bar");
const musicProgressBarCurrent = musicWrap.querySelector(".progress .timer .current");
const musicProgressBarDuration = musicWrap.querySelector(".progress .timer .duration");
let musicIndex = 1; //현재 음악 인덱스
음악 플레이어의 재생,이전곡.다음곡을 위한 선택자 입니다.
window.addEventListener("load", () => {
loadMusic(musicIndex);
});
웹페이지가 로드될 때, loadMusic 함수를 실행하는 이벤트 리스너를 등록하는 코드입니다.
window는 웹페이지의 창을 의미하는 전역 객체입니다.
// 플레이 버튼 클릭
musicPlay.addEventListener("click", () => {
const isMusicPaused = musicWrap.classList.contains("paused"); //음악 재생중
isMusicPaused ? pauseMusic() : playMusic();
});
// 이전 곡 버튼 클릭
musicPrevBtn.addEventListener("click", () => {
prevMusic();
});
// 다음 곡 버튼 클릭
musicNextBtn.addEventListener("click", () => {
nextMusic();
});
위의 코드는 각 버튼들의 클릭 이벤트 리스너를 등록하는 부분입니다.
musicPlay 버튼을 클릭하면, 먼저 musicWrap 요소에 paused 클래스가 있는지 확인합니다. paused 클래스가 있다면 음악이 재생 중이라는 의미이므로, pauseMusic() 함수를 호출하여 음악을 일시정지합니다. paused 클래스가 없다면 음악이 일시정지 중이라는 의미이므로, playMusic() 함수를 호출하여 음악을 재생합니다.
musicPrevBtn 버튼을 클릭하면 prevMusic() 함수를 호출하여 이전 곡을 재생합니다.
musicNextBtn 버튼을 클릭하면 nextMusic() 함수를 호출하여 다음 곡을 재생합니다.
음악 재생
//음악 재생
const loadMusic = (num) => {
musicName.innerText = allMusic[num-1].name; //뮤직 이름
musicArtist.innerText = allMusic[num-1].artist; //뮤직 아티스트
musicView.src = `img/${allMusic[num-1].img}.png`; //뮤직 이미지
musicView.alt = allMusic[num-1].name; //뮤직 이미지 alt
musicAudio.src = `audio/${allMusic[num-1].audio}.mp3` //뮤직파일
}
이 코드는 loadMusic라는 함수를 정의합니다. 이 함수는 하나의 매개변수 num을 받으며, 선택한 음악의 세부 정보를 페이지의 HTML 요소에 업데이트합니다. 구체적으로, 선택한 음악의 이름과 아티스트를 각각 musicName과 musicArtist라는 id를 가진 HTML 요소의 innerText 속성으로 업데이트합니다. 그리고 선택한 음악의 이미지 파일과 이미지 이름을 각각 musicView라는 id를 가진 HTML img 요소의 src와 alt 속성으로 설정합니다. 마지막으로, 선택한 음악의 오디오 파일을 갖는 HTML audio 요소의 src 속성을 설정합니다.
재생
// 재생
const playMusic = () =>{
musicWrap.classList.add("paused");
musicPlay.setAttribute("title", "정지");
musicPlay.setAttribute("class", "stop");
musicAudio.play();
}
playMusic() 함수는 음악 재생을 담당하는 함수입니다. 이 함수가 실행되면 다음과 같은 일이 일어납니다.
musicWrap 요소에 paused 클래스를 추가합니다. 이는 CSS 스타일링을 통해 재생/일시정지 버튼의 디자인을 변경하는 역할을 합니다.
musicPlay 요소의 title 속성 값을 "정지"로 변경합니다. 이는 마우스를 올리면 툴팁으로 표시되는 메시지입니다.
musicPlay 요소의 class 속성 값을 "stop"으로 변경합니다. 이는 CSS 스타일링을 통해 버튼 모양을 변경하는 역할을 합니다.
musicAudio 요소에 play() 메소드를 호출하여 음악을 재생합니다.
정지
// 정지
const pauseMusic = () =>{
musicWrap.classList.remove("paused");
musicPlay.setAttribute("title", "재생");
musicPlay.setAttribute("class", "play");
musicAudio.pause();
}
pauseMusic() 함수는 음악 일시정지를 담당하는 함수입니다. 이 함수가 실행되면 다음과 같은 일이 일어납니다.
musicWrap 요소에서 paused 클래스를 제거합니다. 이는 CSS 스타일링을 통해 재생/일시정지 버튼의 디자인을 변경하는 역할을 합니다.
musicPlay 요소의 title 속성 값을 "재생"으로 변경합니다. 이는 마우스를 올리면 툴팁으로 표시되는 메시지입니다.
musicPlay 요소의 class 속성 값을 "play"로 변경합니다. 이는 CSS 스타일링을 통해 버튼 모양을 변경하는 역할을 합니다.
musicAudio 요소에 pause() 메소드를 호출하여 음악을 일시정지합니다.
이전 곡 / 다음 곡 듣기
// 이전 곡 듣기
const prevMusic = () =>{
musicIndex == 1 ? musicIndex = allMusic.length : musicIndex--;
loadMusic(musicIndex);
playMusic();
}
// 다음 곡 듣기
const nextMusic = () =>{
musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
loadMusic(musicIndex);
playMusic();
}
prevMusic() 함수는 이전 곡을 재생하는 함수입니다. 이 함수가 실행되면 다음과 같은 일이 일어납니다.
현재 재생 중인 음악의 인덱스 musicIndex를 확인합니다.
musicIndex가 1이면, 현재 재생 중인 음악이 첫 번째 곡이므로, musicIndex를 마지막 곡의 인덱스로 변경합니다.
musicIndex가 1보다 크면, 이전 곡이 있으므로, musicIndex를 1 감소시킵니다.
변경된 musicIndex를 사용하여 loadMusic() 함수를 호출하여 이전 곡을 로드합니다.
playMusic() 함수를 호출하여 이전 곡을 재생합니다.
nextMusic() 함수는 다음 곡을 재생하는 함수입니다. 이 함수가 실행되면 다음과 같은 일이 일어납니다.
현재 재생 중인 음악의 인덱스 musicIndex를 확인합니다.
musicIndex가 allMusic 배열의 마지막 요소의 인덱스와 같으면, 현재 재생 중인 음악이 마지막 곡이므로, musicIndex를 1로 변경합니다.
musicIndex가 allMusic 배열의 마지막 요소의 인덱스보다 작으면, 다음 곡이 있으므로, musicIndex를 1 증가시킵니다.
변경된 musicIndex를 사용하여 loadMusic() 함수를 호출하여 다음 곡을 로드합니다.
playMusic() 함수를 호출하여 다음 곡을 재생합니다.
// 뮤직 진행 바
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}`;
musicProgressBarDuration.innerText = `${totalMin}:${totalSec}`;
});
// 진행 시간
let currentMin = Math.floor(currentTime / 60);
let currentSec = Math.floor(currentTime % 60);
if(currentSec < 10) currentSec = `0${currentSec}`;
musicProgressBarCurrent.innerText = `${currentMin}:${currentSec}`;
});
이 코드는 오디오 플레이어의 뮤직 진행 바를 구현하는 코드입니다.
musicAudio 요소에 timeupdate 이벤트를 등록하여, 오디오가 재생 중일 때마다 발생하는 이벤트를 감지합니다. 이벤트 핸들러 함수에 전달되는 e 객체에서는 target.currentTime으로 현재 재생 중인 오디오의 시간, target.duration으로 오디오의 전체 길이를 가져올 수 있습니다.
이를 이용하여 전체 길이에서 현재 진행되는 시간을 백분위 단위로 계산하여 musicProgressBar의 width를 조정합니다. 또한, loadeddata 이벤트를 등록하여 오디오 파일이 로딩되면 전체 길이(duration)를 계산하여 musicProgressBarDuration에 표시합니다.
마지막으로 현재 진행되는 시간(currentTime)을 계산하여 musicProgressBarCurrent에 표시합니다. Math.floor 함수를 이용하여 분(currentMin)과 초(currentSec)를 계산하고, 문자열 보간법을 사용하여 이를 텍스트로 표시합니다.
timeupdate 이벤트는 HTML5 <audio> 또는 <video> 엘리먼트가 재생되는 동안 실행됩니다. 엘리먼트가 재생되는 동안 일정한 간격으로 발생하여, 엘리먼트의 현재 재생 시간, 현재 버퍼링된 시간, 재생 속도 등과 같은 다양한 정보를 제공합니다.
timeupdate 이벤트를 처리하는 함수에서 e.target.currentTime 프로퍼티를 사용하면, 현재 재생 중인 미디어의 재생 위치를 초 단위로 확인할 수 있습니다. 이 정보를 사용하여, 재생 중인 미디어의 현재 위치에 맞게 UI를 업데이트할 수 있습니다.
loadeddata 이벤트는 미디어 요소(예: <audio>, <video>)의 데이터 로딩이 완료될 때마다 발생하는 이벤트입니다.
이 이벤트는 미디어 요소가 최소한 하나의 프레임의 데이터를 로드할 수 있을 때마다 발생하므로, duration 속성과 같이 미디어의 재생 길이 정보를 얻는 데 사용할 수 있습니다.
즉, loadeddata 이벤트는 미디어 재생을 위해 필요한 정보를 얻을 때 유용하게 사용할 수 있습니다.
진행 버튼
// 진행 버튼 클릭
musicProgress.addEventListener("click", (e) => {
let progressWidth = musicProgress.clientWidth; //전체 바 진행 길이
let clickedOffsetX = e.offsetX; //진행바를 기준으로 측정되는 X좌표 값
let songDuration = musicAudio.duration; //오디오 전체 길이
//백분위로 나눈 숫자에 다시 전체 길이를 곱해서 현재 재생값으로 바꿈
musicAudio.currentTime = (clickedOffsetX / progressWidth) * songDuration;
})
musicProgress.addEventListener를 통해 progress bar를 클릭할 때 이벤트를 등록하고, 클릭한 위치를 구하기 위해 e.offsetX를 사용합니다. 그리고 전체 progress bar의 길이를 구한 후, 이를 기준으로 클릭한 위치의 백분위 값을 계산합니다. 이 값과 오디오 파일의 전체 길이를 곱하면 현재 재생 위치를 계산할 수 있습니다. 계산한 값으로 musicAudio.currentTime을 설정하여 음악을 재생 위치를 찾도록 합니다.