JAVASCRIPT

게임 이펙트 만들기! (뮤직 플레이 기능)

김도현2 2023. 4. 27. 21:18
반응형

게임 이펙트 만들기! (뮤직 플레이 기능)

작은 음악 재생기를 만들어 봤습니다!

 

 

 

 

 

 

 

 

 

 

 

script

const allMusic = [
    {
        name : "1. Here it Comes",
        artist : "TrackTribe",
        img : "musicView01",
        audio : "music_audio01"
    },{
        name : "2. Here it Comes",
        artist : "TrackTribe",
        img : "musicView02",
        audio : "music_audio02"
    },{
        name : "3. Here it Comes",
        artist : "TrackTribe",
        img : "musicView03",
        audio : "music_audio03"
    },{
        name : "4. Here it Comes",
        artist : "TrackTribe",
        img : "musicView04",
        audio : "music_audio04"
    },{
        name : "5. Here it Comes",
        artist : "TrackTribe",
        img : "musicView05",
        audio : "music_audio05"
    },{
        name : "6. Here it Comes",
        artist : "TrackTribe",
        img : "musicView06",
        audio : "music_audio06"
    },{
        name : "7. Here it Comes",
        artist : "TrackTribe",
        img : "musicView07",
        audio : "music_audio07"
    },{
        name : "8. Here it Comes",
        artist : "TrackTribe",
        img : "musicView08",
        audio : "music_audio08"
    },{
        name : "9. Here it Comes",
        artist : "TrackTribe",
        img : "musicView09",
        audio : "music_audio09"
    }
];



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 musicProgressCurrent = musicWrap.querySelector(".progress .timer .current");
const musicProgressDuration = musicWrap.querySelector(".progress .timer .duration");

const musicCount = allMusic.length;

let musicIndex = 6;  // 현재 음악 인덱스

// 음악 재생
const loadMusic = (num) => {
    musicName.innerText = allMusic[num-1].name;             //뮤직 이름
    musicArtist.innerText = allMusic[num-1].artist;         //뮤직 아티스트
    musicView.src = `img/${allMusic[num-1].img}.png`;       //뮤직 이미지
    musicView.art = allMusic[num-1].name;                   //뮤직 이미지 alt
    musicAudio.src = `audio/${allMusic[num-1].audio}.mp3`;   //뮤직파일

}

//재생 버튼
const playMusic = () => {
    musicWrap.classList.add("paused");
    musicPlay.setAttribute("title", "정지");
    musicPlay.setAttribute("class", "stop");
    musicAudio.play();
}

//정지 버튼
const pauseMusic = () => {
    musicWrap.classList.remove("paused");
    musicPlay.setAttribute("title", "재생");
    musicPlay.setAttribute("class", "play");
    musicAudio.pause();
}

// 이전 곡 듣기
const prevMusic = () => {
    musicIndex <= 1 ? musicIndex = 9 : musicIndex --;
    loadMusic(musicIndex);
    musicAudio.play();
}

// 다음 곡 듣기
const nextMusic = () => {
    // musicIndex++;
    // if(musicIndex >= musicCount){
    //     musicIndex= 1;
    // }

    musicIndex >= musicCount ? musicIndex=1 : musicIndex++;
    loadMusic(musicIndex);
    musicAudio.play();
}

// 뮤직 진행바
musicAudio.addEventListener("timeupdate", e => {
    // console.log(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 currntSec = Math.floor(currentTime % 60);
    if(currntSec < 10) currntSec = `0${currntSec}`
    musicProgressCurrent.innerText = `${currentMin}:${currntSec}`;
});

// 진행바 버튼 클릭
musicProgress.addEventListener("click",(e)=>{
    let progressWidth = musicProgress.clientWidth;  //진행바 전체 길이
    let clickedOffsetX = e.offsetX;                 //진행바 기준으로 측정되는 X좌표값
    let songDuration = musicAudio.duration;         //노래 전체 길이

    //백분위 나눈 숫자에 다시 전체 길이를 곱해서 현재 재생값으로 바꿈
    musicAudio.currentTime = (clickedOffsetX/progressWidth) *songDuration;

    // console.log(musicAudio.currentTime)
})

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

});

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

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

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

 

 

 

뮤직 플레이어에 대한 스크립트 부분 입니다.

 

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 musicProgressCurrent = musicWrap.querySelector(".progress .timer .current");
const musicProgressDuration = musicWrap.querySelector(".progress .timer .duration");

const musicCount = allMusic.length;

let musicIndex = 6;  // 현재 음악 인덱스

// 음악 재생
const loadMusic = (num) => {
    musicName.innerText = allMusic[num-1].name;             //뮤직 이름
    musicArtist.innerText = allMusic[num-1].artist;         //뮤직 아티스트
    musicView.src = `img/${allMusic[num-1].img}.png`;       //뮤직 이미지
    musicView.art = allMusic[num-1].name;                   //뮤직 이미지 alt
    musicAudio.src = `audio/${allMusic[num-1].audio}.mp3`;   //뮤직파일

}

".music__wrap" 클래스를 가진 요소를 "musicWrap" 상수에 할당하고, 음악 정보를 출력하는 요소들을 각각 "musicName", "musicArtist", "musicView" 상수에 할당합니다.

 

또한, 실제 음악 파일을 재생하는 audio 요소를 "musicAudio" 상수에 할당하고, 재생 및 이전/다음 곡 재생 버튼 등을 각각 "musicPlay", "musicPrevBtn", "musicNextBtn" 상수에 할당합니다. 이어서, 음악 재생 시간을 표시하는 요소들을 "musicProgress", "musicProgressBar", "musicProgressCurrent", "musicProgressDuration" 상수에 할당합니다.

 

그리고 "allMusic" 배열의 길이를 "musicCount" 상수에 할당하고, 현재 재생 중인 음악의 인덱스를 "musicIndex" 변수에 할당합니다.

 

마지막으로, "loadMusic" 함수를 정의합니다. 이 함수는 인자로 받은 음악 번호(num)에 해당하는 음악 정보를 "allMusic" 배열에서 찾아서, 해당 음악의 이름, 아티스트, 이미지, 파일 경로 등을 각각 해당 요소에 업데이트합니다. 이 함수를 호출하여, 초기에는 "musicIndex" 변수에 할당된 현재 음악 인덱스(여기서는 6)에 해당하는 음악 정보가 페이지 로딩 시 출력됩니다.

 

 

 

 

//재생 버튼
const playMusic = () => {
    musicWrap.classList.add("paused");
    musicPlay.setAttribute("title", "정지");
    musicPlay.setAttribute("class", "stop");
    musicAudio.play();
}

//정지 버튼
const pauseMusic = () => {
    musicWrap.classList.remove("paused");
    musicPlay.setAttribute("title", "재생");
    musicPlay.setAttribute("class", "play");
    musicAudio.pause();
}

// 이전 곡 듣기
const prevMusic = () => {
    musicIndex <= 1 ? musicIndex = 9 : musicIndex --;
    loadMusic(musicIndex);
    musicAudio.play();
}

// 다음 곡 듣기
const nextMusic = () => {
    // musicIndex++;
    // if(musicIndex >= musicCount){
    //     musicIndex= 1;
    // }

    musicIndex >= musicCount ? musicIndex=1 : musicIndex++;
    loadMusic(musicIndex);
    musicAudio.play();
}

 

 

"playMusic"는 재생 버튼 클릭 시 실행됩니다. 이 함수에서는 "paused" 클래스를 "musicWrap" 요소에 추가하여, 재생 중인 상태를 표시합니다. 또한, 버튼의 title 속성을 "정지"로, class 속성을 "stop"으로 변경합니다. 마지막으로, "musicAudio" 요소를 통해 실제 음악 파일을 재생합니다.

 

"pauseMusic"는 정지 버튼 클릭 시 실행됩니다. 이 함수에서는 "paused" 클래스를 "musicWrap" 요소에서 제거하여, 일시 정지 상태를 표시합니다. 또한, 버튼의 title 속성을 "재생"으로, class 속성을 "play"로 변경합니다. 마지막으로, "musicAudio" 요소를 통해 실제 음악 파일을 일시 정지합니다.

 

"prevMusic"는 이전 곡 재생 버튼 클릭 시 실행됩니다. 이 함수에서는 현재 재생 중인 음악의 인덱스를 확인하여, 첫번째 음악인 경우에는 마지막 음악으로 인덱스를 변경하고, 그 외의 경우에는 이전 음악으로 인덱스를 변경합니다. 이후, 변경된 인덱스에 해당하는 음악 정보를 "loadMusic" 함수를 통해 업데이트하고, 해당 음악을 재생합니다.

 

"nextMusic"는 다음 곡 재생 버튼 클릭 시 실행됩니다. 이 함수에서는 현재 재생 중인 음악의 인덱스를 확인하여, 마지막 음악인 경우에는 첫번째 음악으로 인덱스를 변경하고, 그 외의 경우에는 다음 음악으로 인덱스를 변경합니다. 이후, 변경된 인덱스에 해당하는 음악 정보를 "loadMusic" 함수를 통해 업데이트하고, 해당 음악을 재생합니다.

 

 

 

// 뮤직 진행바
musicAudio.addEventListener("timeupdate", e => {
    // console.log(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 currntSec = Math.floor(currentTime % 60);
    if(currntSec < 10) currntSec = `0${currntSec}`
    musicProgressCurrent.innerText = `${currentMin}:${currntSec}`;
});

// 진행바 버튼 클릭
musicProgress.addEventListener("click",(e)=>{
    let progressWidth = musicProgress.clientWidth;  //진행바 전체 길이
    let clickedOffsetX = e.offsetX;                 //진행바 기준으로 측정되는 X좌표값
    let songDuration = musicAudio.duration;         //노래 전체 길이

    //백분위 나눈 숫자에 다시 전체 길이를 곱해서 현재 재생값으로 바꿈
    musicAudio.currentTime = (clickedOffsetX/progressWidth) *songDuration;

    // console.log(musicAudio.currentTime)
})

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

});

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

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

 

loadMusic(num) 함수를 이용하여, 전체 음악 리스트(allMusic) 중에서 num에 해당하는 인덱스에 해당하는 음악을 로드합니다. 이때, 음악 파일, 음악 이름, 아티스트 이름, 음악 이미지 등을 설정합니다.

 

playMusic(), pauseMusic() 함수를 이용하여, 음악을 재생하거나 정지합니다. 재생 버튼을 누르면 음악이 재생되고, 정지 버튼을 누르면 음악이 정지됩니다. 이때, 각각의 버튼에 대한 타이틀 속성과 클래스를 추가 또는 제거하여 버튼의 모양을 변경합니다.

 

prevMusic(), nextMusic() 함수를 이용하여, 이전 곡 또는 다음 곡을 재생합니다. 이때, 현재 재생되는 곡의 인덱스를 저장하는 musicIndex 값을 변경하고, 변경된 인덱스에 해당하는 음악을 로드합니다.

 

뮤직 진행바를 표시하고, 진행바 클릭 이벤트를 처리하는 코드가 있습니다. 음악 재생 시간과 전체 길이를 나타내는 태그도 함께 업데이트됩니다.

 

각 버튼의 클릭 이벤트를 처리하는 코드가 있습니다. playMusic(), pauseMusic(), prevMusic(), nextMusic() 함수를 호출하거나, 뮤직 진행바 클릭 이벤트를 처리합니다.