Winnie The Pooh Bear 자바스크립트 게임 이펙트_음악재생(반복, 재생목록 등)

배움기록/JAVASCRIPT

자바스크립트 게임 이펙트_음악재생(반복, 재생목록 등)

코딩은 처음이라 2023. 5. 4. 15:36

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

자바스크립트 게임 이펙트_음악재생(반복, 재생목록 등)

 

 

 

 

저번에 했던 음악 재생에 이어 오늘은 음악재생 목록 불러오기와 반복재생 등의 작업을 해보겠습니다

전의 작업내용이 궁금하다면 아래 링크로 확인해주세요~!

코드 보기

 

 

 

 

💜 게임 이펙트

코드 보기 / 완성 화면

 

 

HTML

<!-- 뮤직 플레이어 -->
<div class="music__wrap">
    <div class="music__inner">
        <div class="music__header">
            <span class="left"></span>
            <h2>music</h2>
            <span class="right"></span>
        </div>
        <div class="music__contents">
            <div class="music__view">
                <div class="image">
                    <img src="../game/img/music_view01.png" alt="">
                </div>
            </div>
            <div class="music__control">
                <div class="title">
                    <h3>노래 제목</h3>
                    <p>작가 이름</p>
                </div>
                <div class="progress">
                    <div class="bar">
                        <audio id="main-audio" src="audio/music_audio01.mp3"></audio>
                    </div>
                    <div class="timer">
                        <span class="currnet">0:00</span>
                        <span class="duration">3:55</span>
                    </div>
                </div>
                <div class="control">
                    <span>
                        <i class="repeat" id="control-repeat" title="전체 반복"></i>
                        <!-- <i class="repeat_one" id="control-repeat" title="한곡 반복"></i> -->
                        <!-- <i class="shuffle" id="control-repeat" title="랜덤 반복"></i> -->
                    </span>
                    <span>
                        <i class="prev" id="control-prev" title="이전곡 재생"></i>
                    </span>
                    <span>
                        <i class="play" id="control-play" title="재생"></i>
                    </span>
                    <span>
                        <i class="next" id="control-next" title="다음곡 재생"></i>
                    </span>
                    <span>
                        <i class="list" id="control-list" title="재생 목록"></i>
                    </span>
                    <!-- <span class="stop">정지 반복</span> -->
                </div>
            </div>
            <div class="music__list">
                <h3>뮤직 리스트 <a href="#" class="close"></a></h3>
                <ul>
                    <!-- <li class="active">
                        <span class="img">
                            <img src="img/music_view03.png" alt="#">
                        </span>
                        <span class="title">
                            <strong>Who Do You Think I Think You Are</strong><br>
                            <em>Mini Vandals</em>
                        </span>
                        <span class="time">3:04</span>
                    </li> -->
                </ul>
            </div>
        </div>
    </div>
</div>
<!-- //뮤직 플레이어 -->

주석된 곳의 내용을 스크립트로 작업해줍니다.

 

 

 

선택자

const musicRepeat = musicWrap.querySelector("#control-repeat");
const musicListBtn = musicWrap.querySelector("#control-list")
const musicList = musicWrap.querySelector(".music__list");
const musicListUl = musicWrap.querySelector(".music__list ul");
const musicListClose = musicWrap.querySelector(".music__list h3 .close");

작업해줄곳의 선택자를 추가해줍니다.

 

 

반복버튼

//반복 버튼 클릭
musicRepeat.addEventListener("click", () => {
    let getAttr = musicRepeat.getAttribute("class");

    switch (getAttr) {
        case "repeat":
            musicRepeat.setAttribute("class", "repeat_one");
            musicRepeat.setAttribute("title", "한곡 반복");
            break;
        case "repeat_one":
            musicRepeat.setAttribute("class", "shuffle");
            musicRepeat.setAttribute("title", "랜덤 반복");
            break;
        case "shuffle":
            musicRepeat.setAttribute("class", "repeat");
            musicRepeat.setAttribute("title", "전체 반복");
            break;
    }
});

반복 버튼을 클릭할때마다 버튼의 클래스와 title을 바꿔줍니다.

 

musicRepeat라는 변수는 HTML 문서에서 반복 버튼을 가리키는 역할

musicRepeat.addEventListener는 musicRepeat 버튼에 클릭 이벤트를 추가

 

let getAttr = musicRepeat.getAttribute("class");는 현재 musicRepeat 버튼의 클래스를 가져와 getAttr 변수에 저장

 

✨setAttribute() : HTML요소의 속성 값을 변경

switch문 :  getAttr변수에 따라 버튼의 클래스와 title속성을 변경

case repeat : 버튼의 클래스를 repeat_one으로 변경, 버튼의 title속성을 한곡 반복으로 변경

case repeat_one : 버튼의 클래스를 shuffle로 변경, 버튼의 title 속성을 랜덤반복으로 변경

case shuffle : 버튼의 클래스를 repeat으로 변경, 버튼의 title 속성을 전체 반복으로 변경

 

 

오디오가 끝났을때

//오디오가 끝나면
musicAudio.addEventListener("ended", () => {
    let getAttr = musicRepeat.getAttribute("class");

    switch (getAttr) {
        case "repeat":
            nextMusic();
            break;
        case "repeat_one":
            playMusic();
            break;
        case "shuffle":
            let randomIndex = Math.floor(Math.random() * allMusic.length + 1);    //랜덤 인덱스 생성

            do {
                randomIndex = Math.floor(Math.random() * allMusic.length + 1);
            } while (musicIndex == randomIndex);

            musicIndex = randomIndex;    //현재 인덱스를 랜덤 인덱스로 변경
            loadMusic(randomIndex);
            playMusic();
            
            break;
    }
    playListMusic();
});

musicAudio 오디오 요소에서 ended 이벤트가 발생했을때 실행되는 콜백 함수입니다.

 

getAttr 변수에 현재 반복 모드를 저장,

switch문에서 getAttr변수의 값에 따라 다음과 같은 동작 수행

 

repeat : nestMusic() 함수를 호출해 다음 곡을 재생

repeat_one : palyMusic() 함수를 호출해 현재 곡을 다시 재생

shuffle :  allMusic 배열의 길이를 이용해 0에서 -1 범위의 랜덤한 인덱스를 생성,  생성한 랜덤의 인덱스가 현재 인덱스와 같다면 다시 랜덤한 인덱스를 생성하고, 현재 인덱스와 다른 랜덤한 인덱스가 생성될때까지 반복

 

musicIndex 변수에 랜덤한 인덱스 값을 할당하고 loadMusic() 함수를 호출해 선택된 랜덤한 곡을 로드해 playMusic()함수를 호출해 해당 곡을 재생시킵니다.

 

 

버튼클릭시

//플레이 버튼 클릭
musicPlay.addEventListener("click", () => {
    const isMusicPaused = musicWrap.classList.contains("paused");    //음악 재생중
    isMusicPaused ? pauseMusic() : playMusic();
});

//이전곡 버튼 클릭
musicPrevBtn.addEventListener("click", () => {
    prevMusic();
});

//다음곡 버튼 클릭
musicNextBtn.addEventListener("click", () => {
    nextMusic();
});

//뮤직 리스트 버튼
musicListBtn.addEventListener("click", () => {
    musicList.classList.add("show");
});
//뮤직 리스트 닫기 버튼
musicListClose.addEventListener("click", () => {
    musicList.classList.remove("show");
});

다양한 버튼 클릭 시 실행되는 콜백 함수

 

musicPlay : 현재 음악이 일시정지 중인지 아닌지를 확인, 일시정지 중이라면 pauseMuisc()함수를 아니라면 playMusic()함수를 호출해 음악을 일시정지하거나 재생

musicPrevBtn : prevMusic() 함수를 호출해 이전 곡을 재생

musicNextBtn : nextMusic()함수를 호출해 다음 곡을 재생

musicListBtn : musicList 요소에 show 클래스를 추가해 음악 리스트를 보여줌

musicLiscClose :  musicList 요소에 show 클래스를 제거해 음악 리스트를 숨김

 

 

뮤직 리스트

//뮤직 리스트 구현하기
for (let i = 0; i < allMusic.length; i++) {
        let li = `
    <li data-index="${i+1}">
        <span class="img">
            <img src="img/${allMusic[i].img}.png" alt=${allMusic[i].name}>
        </span>
        <span class="title">
            <strong>${allMusic[i].name}</strong><br>
            <em>${allMusic[i].artist}</em>
            <audio class="${allMusic[i].audio}" src="audio/${allMusic[i].audio}.mp3"></audio>
        </span>
        <span class="audio-duration" id="${allMusic[i].audio}">3:04</span>
    </li>
    `;

    // musicListUl.innerHTML += li;
    musicListUl.insertAdjacentHTML("beforeend", li);

    //리스트에 음악 시간 불러오기
    let liAudioDuraion = musicListUl.querySelector(`#${allMusic[i].audio}`);   //리스트에서 시간을 표시할 선택자
    let liAudio = musicListUl.querySelector(`.${allMusic[i].audio}`);           //리스트에서 오디오 파일 선택자
    liAudio.addEventListener("loadeddata", () => {
        let audioDuration = liAudio.duration;
        // console.log(audioDuration);
        let totalMin = Math.floor(audioDuration / 60);
        let totalSec = Math.floor(audioDuration % 60);
        if(totalSec < 10) totalSec = `0${totalSec}`;
        liAudioDuraion.innerText = `${totalMin}:${totalSec}`;
        liAudioDuraion.setAttribute("data-duration", `${totalMin}:${totalSec}`);
    });
}

for문을 사용해  allMusic 배열에 저장된 음악 정보를 이용해 각각의 li 요소를 생성

li요소는 음악 정보를 보여주는 이미지, 음악제목, 가수이름 등의 정보를 포함

또한 li요소에는 음악 파일을 재생하기 위한 audio 요소가 포함

 

생성된 li요소는 musicListUl변수가 참조하는 ul 요소의 innerHTML 속성을 이용해 ul 요소에 추가 

insertAdjacentHTML 메서드를 사용해 마지막 요소 이후에 추가가능

 

마지막으로 각각의 li 요소에 음악 파일의 재생 시간을 나타내는 audio-duration 클래스를 가진 span요소가 포함되어 있습니다.

이 요소는 liadeddata 이벤트를 이용해 음악 파일의 재생 시간을 가지고 온 후 표시됩니다.

 

 

뮤직리스트 클릭시 재생

//뮤직 리스트를 클릭하면 재생
function playListMusic(){
    const musicListAll = musicListUl.querySelectorAll("li");   //뮤직 리스트 목록

    for(let i=0; i<musicListAll.length; i++){
        let audioTag = musicListAll[i].querySelector(".audio-duration");

        musicListAll[i].setAttribute("onclick", "clicked(this)");

        if(musicListAll[i].classList.contains("playing")){
            musicListAll[i].classList.remove("playing");
            let dataAudioDuration = audioTag.getAttribute("data-duration");
            audioTag.innerText = dataAudioDuration;
        }

        if(musicListAll[i].getAttribute("data-index") == musicIndex){
            musicListAll[i].classList.add("playing");
            audioTag.innerText = "재생중";
        }
    }
}

audio-duration클래스를 가진 span요소를 선택

setAttribute 메서드를 사용해 클릭 이벤트가 발생하면 clicked(this)함수를 호출하도록 onclick 속성을 추가

현재 재생 중인 곡을 나타내는 playing 클래스를 가지고 있다면 해당 클래스를 제거하고, 이전에 설정된 오디오 시간으로 innerText 를 변경

현재 선택된 고과 musicIndex가 일치하는 경우 playing 클래스를 추가하고 innerText 를 재생중으로 변경

 

 

뮤직 리스트 클릭

//뮤직 리스트를 클릭하면
function clicked(el){
    let getIndex = el.getAttribute("data-index");
    // alert(getIndex);

    musicIndex = getIndex;
    loadMusic(musicIndex);
    playMusic();
    playListMusic();

}

window.addEventListener("load", () => {
    loadMusic(musicIndex);
    playListMusic();
});

cliced()함수는 클릭된 요소의 data-index 속성값을 가져와서 getIndex 그 값을 musicIndex 변수에 저장하고, 해당 인덱스에 해당하는 뮤직 파일을 로드하고 재생합니다.

playListMusic()함수를 호출하여 뮤직 리스트에서 재생 중인 곡을 표시

 

또한 window 객체에 load 이벤트를 등록해 웹 페이지가 로드될 때 loadMusic() 와 playListMusic() 함수를 호출해 초기 뮤직 파일을 로드하고 뮤직 리스트를 초기화합니다.

 

 

반응형