필요없는 목록/JAVASCRIPT

간단한 게임 만들기 - 음악리스트 (3 / 5)

비밀안 2023. 5. 4. 21:24
클릭

버튼을 클릭하면 명언이 나와요

-

이름이 나와요

게임 메인 화면 만들기2 주소

https://skadldldl123.tistory.com/94

 

간단한 게임 만들기 음악 리스트 페이지 꾸며보기 2 / 5

최종 완성된 모습 HTML 삽입 미리보기할 수 없는 소스 저번에 만들었던 메인페이지 제작을 완료 한 뒤에 음악 리스트 페이지를 만들었습니다. 음악리스트 넣은 모습 JAVASCRIPT코드 const musicWrap = docu

skadldldl123.tistory.com

메인화면 만들기 3번은 게임 메인화면 만들기 2번에서 만들었던

재생목록 창에다가 효과를 넣어주는 것을 해봤어요.

 

재생 목록, 반복 듣기, 1번만 듣기, 자동 재생 HTML코드

<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="repeat_one"><i class="repeat_one">한곡 반복</i></span>
    <span class="shuffle"><i class="shuffle">랜덤 반복</i></span>
    <span class="stop"><i class=stop>반복</i></span> -->
</div>

<div class="music__list">
    <h3>뮤직 리스트 <a href="#" class="close"></a></h3>
    <ul>
        <!-- strong이나 em,span태그 -->
        <!-- <li class="active">
            <div class="list__box">
                <div class="list__img">
                    <img src="/assets/javascript/game/img/music_view01.png">
                </div>
                <div class="list__name">
                    <p>1.아티스트</p>
                    <span>이름</span>
                </div>
                <div class="list__time">
                    <p>02:43</p>
                </div>
            </div>
        </li> -->
</div>

코드 설명

 

재생 목록, 반복 듣기, 1번만 듣기, 자동 재생 JAVASCRIPT코드

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 getArr = musicRepeat.getAttribute("class");
    
    switch(getArr){
        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;
    }
});


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

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

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

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

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

// 뮤직 리스트 구현하기
for(let i=0; i<allMusic.length; i++){
    // data-index="" 각각의 li태그에 데이터값을 부여 함.
    let li = `
        <li data-index="${i+1}">
            <div class="list__box">
                <div class="list__img">
                    <img src="/assets/javascript/game/img/${allMusic[i].img}.png">
                </div>
                <div class="list__name">
                    <p>${allMusic[i].name}</p>
                    <span>${allMusic[i].artist}</span>
                    <audio class="${allMusic[i].audio}" src="audio/${allMusic[i].audio}.mp3"></audio>
                </div>
                <span class="audio-duration" id="${allMusic[i].audio}">3:04</span>
            </div>
        </li>
    `;

    const musicListLi = musicWrap.querySelectorAll(".music__list ul li");  
    // musicListLi.forEach((el, index, array) => {
    //     musicListLi[index].addEventListener("click", () => {
    //         musicListLi[index].classList.add("active");
    //         console.log(musicListLi[index]);
    //     });
    //     // musicListLi[i].classList.remove("active");
    // });

    // musicListUl.innerHTML += li;                     // 이것도 되고
    musicListUl.insertAdjacentHTML("beforeend", li);    // 최근에 많이 쓰이는 방식(참고 : https://webclub.tistory.com/535)

    // 리스트에 음악 시간 불러오기
    let liAudioDuration = 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}`;
        liAudioDuration.innerText = `${totalMin} : ${totalSec}`;
        liAudioDuration.setAttribute("data-duration", `${totalMin} : ${totalSec}`);
    });    
}

// 뮤직 리스트를 클릭하면 재생
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 = "재생중";
        }
    }
}

// 뮤직 리스크를 클릭하면
function clicked(el){
    let getIndex = el.getAttribute("data-index");
    // alert(getIndex);
    musicIndex = getIndex;
    loadMusic(musicIndex);
    playMusic();
    playListMusic();
}

코드 설명

1.

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");
const musicAudio = musicWrap.querySelector("#main-audio");

querySelector()로 태그, 아이디, 클래스를 찾습니다.

 

2.

// 반복 버튼 클릭
musicRepeat.addEventListener("click", () => {
    let getArr = musicRepeat.getAttribute("class");
    
    switch(getArr){
        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;
    }
});

div태그인 .control 안에 i태그 #control-repeat를 클릭하게 되면 

let getArr에  i태그 #control-repeat의 class값을 저장합니다.

 

그리고 class의 이름으로 switch문을 실행합니다.

 

3.

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

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

1.musicListBtn은 div태그인 .control 안에 i태그 #control-list를 클릭하게 되면 

div태그인  .music__list의 내용을 숨기거나 보여줍니다.

 

2.musicListClose은 div태그 .music__list 안에 a태그인 .close를 클릭하게 되면

div태그인  .music__list의 class를 지웁니다.

 

4.

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

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

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

1.musicAudio라는 오디오 요소에 "ended" 이벤트 리스너를 추가하는 것을 보여줍니다. "ended" 이벤트는 오디오 재생이 끝났을 때 발생합니다.

2.이벤트 리스너 콜백 함수 내에서는 musicRepeat 요소의 클래스를 가져옵니다. 그리고 가져온 클래스 값을 switch 문을 사용하여 처리합니다.

3.case "repeat": "repeat" 클래스가 있는 경우 다음 음악을 재생하고 "repeat"을 콘솔에 출력합니다.
4.case "repeat_one": "repeat_one" 클래스가 있는 경우 현재 음악을 다시 재생하고 "repeat_one"을 콘솔에 출력합니다.
5.case "shuffle": "shuffle" 클래스가 있는 경우, 먼저 Math.random() 함수를 사용하여 0 이상 1 미만의 난수를 생성합니다. 6.이 난수를 이용하여 allMusic 배열의 랜덤 인덱스를 얻습니다. 그리고 이 인덱스가 현재 재생 중인 음악의 인덱스와 같지 않을 때까지 반복하여 다른 인덱스를 얻습니다. 그 후, musicIndex 변수의 값을 랜덤 인덱스로 변경하고, loadMusic 함수를 사용하여 해당 인덱스의 음악을 로드한 후 재생합니다. 마지막으로 "shuffle"을 콘솔에 출력합니다.
playListMusic 함수는 이 코드에는 없지만, 아마도 재생 목록의 음악을 업데이트하는 데 사용되는 함수일 것입니다.

7.즉, 이 코드는 음악 플레이어에서 반복 재생 및 셔플 기능을 구현하기 위해 사용될 수 있습니다. 각 클래스에 따라 다른 동작이 수행되며, 재생 목록의 음악을 관리하고 다음 음악을 재생하는 등의 작업을 수행합니다.

 

5.

// 뮤직 리스트 구현하기
for(let i=0; i<allMusic.length; i++){
    // data-index="" 각각의 li태그에 데이터값을 부여 함.
    let li = `
        <li data-index="${i+1}">
            <div class="list__box">
                <div class="list__img">
                    <img src="/assets/javascript/game/img/${allMusic[i].img}.png">
                </div>
                <div class="list__name">
                    <p>${allMusic[i].name}</p>
                    <span>${allMusic[i].artist}</span>
                    <audio class="${allMusic[i].audio}" src="audio/${allMusic[i].audio}.mp3"></audio>
                </div>
                <span class="audio-duration" id="${allMusic[i].audio}">3:04</span>
            </div>
        </li>
    `;

    const musicListLi = musicWrap.querySelectorAll(".music__list ul li");  
    // musicListLi.forEach((el, index, array) => {
    //     musicListLi[index].addEventListener("click", () => {
    //         musicListLi[index].classList.add("active");
    //         console.log(musicListLi[index]);
    //     });
    //     // musicListLi[i].classList.remove("active");
    // });

    // musicListUl.innerHTML += li;                     // 이것도 되고
    musicListUl.insertAdjacentHTML("beforeend", li);    // 최근에 많이 쓰이는 방식(참고 : https://webclub.tistory.com/535)

    // 리스트에 음악 시간 불러오기
    let liAudioDuration = 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}`;
        liAudioDuration.innerText = `${totalMin} : ${totalSec}`;
        liAudioDuration.setAttribute("data-duration", `${totalMin} : ${totalSec}`);
    });    
}

1.allMusic 배열에 저장된 각 음악에 대해 리스트 아이템을 생성하고 HTML에 동적으로 추가합니다.

2.for 루프를 사용하여 allMusic 배열의 각 요소에 대해 반복합니다. 각 음악에 대한 정보를 사용하여 리스트 아이템을 생성하고 변수 li에 할당합니다.

3.li 변수에는 음악의 이미지, 제목, 아티스트, 오디오 요소와 시간 표시를 위한 span 요소가 포함되어 있습니다. 각 정보는 allMusic 배열의 해당 인덱스에서 가져옵니다.

4.리스트 아이템을 생성한 후, 이미 존재하는 musicListUl 요소에 insertAdjacentHTML 메서드를 사용하여 생성된 li를 추가합니다. beforeend 위치에 추가되므로 리스트의 맨 뒤에 추가됩니다.

 

6.

// 뮤직 리스트를 클릭하면 재생
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 = "재생중";
        }
    }
}

// 뮤직 리스크를 클릭하면
function clicked(el){
    let getIndex = el.getAttribute("data-index");
    // alert(getIndex);
    musicIndex = getIndex;
    loadMusic(musicIndex);
    playMusic();
    playListMusic();
}

1.playListMusic() 함수는 뮤직 리스트의 모든 항목을 선택하고(musicListAll 변수), 각 항목에 대해 반복문을 실행합니다. 각 항목에 클릭 이벤트를 추가하기 위해 setAttribute("onclick", "clicked(this)")를 사용합니다. 이렇게 설정된 클릭 이벤트는 clicked 함수를 호출하며, 클릭된 항목(this)을 전달합니다.

2.반복문 내에서는 다음 작업을 수행합니다:

3.playing 클래스가 있는 경우, 해당 항목에서 playing 클래스를 제거하고, 오디오 재생 시간을 원래 값으로 복원합니다.
현재 재생 중인 음악의 인덱스와 리스트 항목의 data-index 속성 값이 일치하는 경우, 해당 항목에 playing 클래스를 추가하고, 오디오 재생 시간을 "재생중"으로 표시합니다.


4.clicked(el) 함수는 뮤직 리스트 항목이 클릭되었을 때 호출됩니다. 클릭된 항목의 data-index 속성 값을 가져와 getIndex 변수에 할당합니다. 그 후, musicIndex 변수를 클릭된 항목의 인덱스로 업데이트하고, loadMusic 함수를 사용하여 해당 음악을 로드한 후 playMusic 함수를 호출하여 재생합니다. 마지막으로 playListMusic 함수를 호출하여 뮤직 리스트의 상태를 업데이트합니다.

5.즉, 이 코드를 사용하면 뮤직 리스트의 항목을 클릭하면 해당 음악이 재생되고, 재생 중인 음악은 "playing" 클래스가 추가되며, 오디오 재생 시간은 "재생중"으로 표시됩니다.

 

인공지능이란 참 좋은 것 같네요.

학원 분량을 못 따라가서 몸이 참 힘드네요