Animated Turtle

Javascript

Game Effect 페이지 만들기 (2)

훙구 2023. 4. 27. 23:48

...

728x90
반응형

Game Effect 페이지 만들기 (2)

이번에는 음악 플레이어 기능을 만들어 보겠습니다.

 

HTML 작성하기

<div class="music__wrap">
    <div class="music__inner">
        <div class="music__header">
            <span class="left"></span>
            <h2>Hoong Player🎧</h2>
            <span class="right"></span>
        </div>
        <div class="music__contents">
            <div class="music__view">
                <div class="image">
                    <img src="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="current">0:00</span>
                        <span class="duration">3:55</span>
                    </div>
                </div>
                <div class="control">
                    <span>
                        <i class="repeat" 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">한곡 반복</span>
                    <span class="shuffle">랜덤 반복</span>
                    <span class="stop">정지 반복</span> -->
                </div>
            </div>
        </div>
        <div class="music__footer"></div>
    </div>
</div>

HTML 정리해보기

  • html 문서에 추가된 내용은 뮤직 플레이어 부분입니다.
  • 버튼은 각각의 span태그로 영역을 잡고 i태그를 사용해 배경이미지를 넣었습니다.
  • 주석처리 부분은 스크립트로 처리하기 위한 영역입니다.

Javascript 작성하기

const allMusic = [
    {
        name : "I Found Her",
        artist : "Faime",
        img : "music__view01",
        audio : "music_audio01"
    },{
        name : "Let",
        artist : "Vietra",
        img : "music__view02",
        audio : "music_audio02"
    },
    {
        name : "Stressin'",
        artist : "Airr",
        img : "music__view03",
        audio : "music_audio03"
    },
    {
        name : "Side Effects",
        artist : "wip",
        img : "music__view04",
        audio : "music_audio04"
    },
    {
        name : "flowers",
        artist : "honeywhip",
        img : "music__view05",
        audio : "music_audio05"
    },
    {
        name : "Summer Is for Falling in Love",
        artist : "Sarah Kang",
        img : "music__view06",
        audio : "music_audio06"
    },
    {
        name : "For you",
        artist : "Vietra",
        img : "music__view07",
        audio : "music_audio07"
    },
    {
        name : "Foolish",
        artist : "Faime",
        img : "music__view08",
        audio : "music_audio08"
    },
    {
        name : "You set my world on fire",
        artist : "Adelyn Paik",
        img : "music__view09",
        audio : "music_audio09"
    },{
        name : "couldn't say it to your face",
        artist : "honeywhip",
        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 musicProgressCurrent =musicWrap.querySelector(".timer .current");
const musicProgressDuration =musicWrap.querySelector(".timer .duration");
const musicCount = allMusic.length;

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

// 음악 재생
const loadMusic = (num) => {
    musicName.innerHTML = allMusic[num-1].name;             // 재생되고 있는 음악 제목 바꾸기
    musicArtist.innerHTML = 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`   // 재생되고 있는 음악 바꾸기
};

// 재생
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--;
    // if(musicIndex == 0) {musicIndex=10};
    musicIndex == 1 ? musicIndex = musicCount : musicIndex--;

    loadMusic(musicIndex);
    playMusic();
};

// 다음 곡 
const nextMusic = () => {
    // musicIndex++;
    // if(musicIndex == 10) {musicIndex=1};
    musicIndex == musicCount ? musicIndex = 1 : musicIndex++;

    loadMusic(musicIndex);
    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}`;
        
        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;                     // 진행바를 기준으로 측정되는 X좌표 값
    let songDuration = musicAudio.duration;             // 오디오 전체 길이

    musicAudio.currentTime = (clickedOffsetX/progressWidth) * songDuration;     // 퍼센티지에 맞는 시간대로 변경

});

// 플레이 버튼 클릭
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);
});

Javascript 정리해보기

  • 각각의 노래에 대한 제목, 가수, 사진, 오디오에 대한 정보를 배열(allMusic) 속 객체 형식으로 저장합니다.
  • 필요한 선택자를 만듭니다.
  • 매개변수로 전달할 musicIndex 변수를 만들어 초기값 1을 저장합니다.

 

  • loadMusic(num) 함수 : 음악 불러오기
  • 매개변수로 받아오는 num을 사용합니다. (musicIndex 를 받아올 예정)
  • allMusic의 num-1 인덱스의 name을 불러와 musicName에 출력합니다.
  • allMusic의 num-1 인덱스의 artist을 불러와 musicArtist에 출력합니다.
  • 이미지의 속성값을 allMusic의 num-1 인덱스의 img로 변경합니다. (alt도 name으로 변경)
  • 오디오의 속성값을 allMusic의 num-1 인덱스의 audio로 변경합니다.

 

  • playMusic() 함수 : 음악 재생
  • musicWrap의 classList에 paused를 추가합니다.
  • musicPlay의 title 속성을 "정지"로 변경합니다.
  • musicPlay의 class 속성을 "stop"으로 변경합니다.
  • musicAudio를 play 합니다.

 

  • pauseMusic() 함수 : 음악 일시정지
  • musicWrap의 classList에 paused를 제거합니다.
  • musicPlay의 title 속성을 "재생"으로 변경합니다.
  • musicPlay의 class 속성을 "play"으로 변경합니다.
  • musicAudio를 pause 합니다.

 

  • prevMusic() 함수 : 이전 음악 재생
  • musicIndex의 값이 1 이라면 musicIndex에 musicCount(allMusic.length)를 저장하고 1이 아니라면 musicIndex에 --연산을 해줍니다.
  • loadMusic(musicIndex) 함수와 playMusic() 함수를 실행합니다.

 

  • nextMusic() 함수 : 다음 음악 재생
  • musicIndex의 값이 musicCount와 같다면 musicIndex에 1을 저장하고 같지 않다면 musicIndex에 ++연산을 해줍니다.
  • loadMusic(musicIndex) 함수와 playMusic() 함수를 실행합니다.

 

  • musicAudio의 timeupdate에 따른 함수를 실행합니다.
  • currentTime에는 현재 진행되고 있는 시간의 정보가 있는 target.currentTime의 값을 저장합니다.
  • duration에는 현재 오디오의 총 길이 정보가 있는 target.duration의 값을 저장합니다
  • progressWidth에는 currentTime 을 duration으로 나눈 값의 100배를 저장합니다. (현재 진행 퍼센티지)
  • musicProgressBar의 width 값을 (progressWidth)%로 설정합니다. (현재 진행 정도를 나타내는 바)

 

  • musicAudio의 loadeddata에 따른 함수를 실행합니다.
  • audioDuration에 musicAudio의 duration(총 길이) 값을 저장합니다.
  • totalMin에 audioDuration을 60으로 나눈값을 내림하여 저장합니다. (분)
  • totalSec에 audioDuration을 60으로 나눈 나머지값을 내림하여 저장합니다. (초)
  • totalSec가 10보다 작다면 앞에 0을 붙여줍니다.
  • musicProgressDuration에 출력합니다.

 

  • 위와 같은 방법으로 timeupdate에 따른 함수에서도 현재 진행되고 있는 부분의 시간을 출력합니다.

 

  • musicProgress의 click에 따른 함수를 실행합니다.
  • progressWidth에 musicProgress의 clientWidth(넓이)값을 저장합니다.
  • clickedOffsetX에 현재 마우스의 진행바 기준 X축 좌표를 저장합니다.
  • songDuration에 musicAudio의 duration(음악 총 길이)값을 저장합니다.
  • musicAudio의 currentTime을 clickOffsetX를 progressWidth값으로 나눈 값에 songDuration을 곱한 값으로 설정합니다. ( 현재 진행 정도 퍼센티지에 맞는 각 음악의 시간대로 변경)

 

  • musicPlay의 click에 따른 함수를 실행합니다.
  • isMusicPaused에는 musicWrap의 classList에 paused가 있는지 확인한 값을 저장합니다.
  • isMusicPaused가 true라면 pauseMusic 함수를, false라면 playMusic 함수를 실행합니다.

 

  • 나머지도 각각의 버튼에 맞는 함수를 실행합니다.

 

 

 

이상으로 게임페이지의 음악 플레이어를 만들어보았습니다 !

 

728x90
반응형