필요없는 목록/CSS 스타일

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

비밀안 2023. 4. 27. 14:11
클릭

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

-

이름이 나와요

최종 완성된 모습

저번에 만들었던 메인페이지 제작을 완료 한 뒤에

음악 리스트 페이지를 만들었습니다.

 

음악리스트 넣은 모습

 

JAVASCRIPT코드

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

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

// 음악 재생
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`;  //뮤직 파일
}

// 재생  
const playMusic = () => {
    musicWrap.classList.add("paused");

    musicPlay.setAttribute("title", "정지");
    musicPlay.setAttribute("class", "stop");

    // play() : 재생 시작
    musicAudio.play();
}

// 정지 
const pauseMusci = () => {
    musicWrap.classList.remove("paused");
    musicPlay.setAttribute("title", "재생");
    musicPlay.setAttribute("class", "play");

    // pause() : 재생 중지
    musicAudio.pause();
}

// 이전 곡 듣기 
const prevMusic = () => {
    musicIndex == 1 ? musicIndex = allMusic.length : musicIndex--;
    loadMusic(musicIndex);
    playMusic();
}

// 다음 곡 듣기 
const nextMusic = () => {
    musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
    loadMusic(musicIndex);
    playMusic();

    // if(musicIndex === allMusic.length) musicIndex = 0;
}

// 뮤직 진행바
musicAudio.addEventListener("timeupdate", e => {
    // console.log(e);

    const currentTime = e.target.currentTime;   //현재 재생 시간
    const duration = e.target.duration;         //오디오의 총 길이
    let progrossWidth = (currentTime/duration) * 100; //전체 길이에서 현재 진행되는 시간을 백분위 단위로 나누면 현재 진행상태를 알수 있음

    musicPregressBar.style.width = `${progrossWidth}%`;

    // 전체 시간
    musicAudio.addEventListener("loadeddata", () => {
        let audioDuration = musicAudio.duration;
        let totalMin = Math.floor(audioDuration / 60);
        let totalSec = Math.floor(audioDuration % 60);

        if(totalMin < 10) totalMin = `0${totalMin}`;
        if(totalSec < 10) totalSec = `0${totalSec}`;

        musicProgressDuration.innerText = `${totalMin}:${totalSec}`;        
    });

    // 진행 시간
    let currentMin = Math.floor(currentTime / 60);
    let currentSec = Math.floor(currentTime % 60);

    if(currentMin < 10) currentMin = `0${currentMin}`;
    if(currentSec < 10) currentSec = `0${currentSec}`;

    musicProgressCurrent.innerText = `${currentMin}:${currentSec}`;
});

// 진행 버튼 클릭
musicPregress.addEventListener("click", (e) => {
    let progressWidth = musicPregress.clientWidth;  //진행바 전체 길이
    let clickOffsetX = e.offsetX;                   //진행바를 기준으로 측정되는 X값 좌펴
    let songDuration = musicAudio.duration;          //오디오 전체 길이
    //백분위로 나눈 숫자에 다시 전체 길이를 곱해 현재 재생값으로 바꿈
    musicAudio.currentTime = (clickOffsetX /progressWidth) * songDuration;
});

// 플레이 클릭
musicPlay.addEventListener("click", () => {
    // "" : 빈 문자열은 "거짓"임
    const isMusicPaused = musicWrap.classList.contains("paused");   //음악 재생 중
    isMusicPaused ? pauseMusci() : playMusic();

    // playMusic();
});

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

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


// 그런데 load 이벤트는 문서내의 모든 리소스(이미지, 스크립트)의 
// 다운로드가 끝난 후에 실행된다. 이것을 에플리케이션의 구동이 
// 너무 지연되는 부작용을 초래할 수 있다.
window.addEventListener("DOMContentLoaded", () => {
    loadMusic(musicIndex);
});

코드 설명

1.

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

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

 

2.

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

// 음악 재생
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`;  //뮤직 파일
}
  • let musicIndex는 음악이 몇번째 음악인지 알려줄 변수입니다.
  • 대상.innerText로 해당 대상의 Text를 변경합니다
  • 대상.src로 이미지와 태그를 변경합니다.
  • 대상.alt는 웹표준 준수를 위해서 이미지 태그에 alt를 줬습니다.

3.

// 재생  
const playMusic = () => {
    musicWrap.classList.add("paused");

    musicPlay.setAttribute("title", "정지");
    musicPlay.setAttribute("class", "stop");

    // play() : 재생 시작
    musicAudio.play();
}

// 정지 
const pauseMusci = () => {
    musicWrap.classList.remove("paused");
    
    musicPlay.setAttribute("title", "재생");
    musicPlay.setAttribute("class", "play");

    // pause() : 재생 중지
    musicAudio.pause();
}

// 이전 곡 듣기 
const prevMusic = () => {
    musicIndex == 1 ? musicIndex = allMusic.length : musicIndex--;
    
    loadMusic(musicIndex);
    playMusic();
}

// 다음 곡 듣기 
const nextMusic = () => {
    musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
    
    loadMusic(musicIndex);
    playMusic();
}

1. playMusic() 익명 함수

  • 대상.classList.add()로 해당 태그에 클래스를 부여합니다.
  • 대상.setAttribute()로 대상의 속성값을 변경합니다.
  • musicAudio.play()는 노래를 재생 시켜줍니다.

2. pauseMusci() 익명 함수

  • 대상.classList.remove()로 해당 태그에 클래스를 지웁니다.
  • 대상.setAttribute()로 대상의 속성값을 변경합니다.
  • musicAudio.pause()는 노래를 재생 시켜줍니다.

3. prevMusic() 익명 함수

  • let musicIndex의 값이 1일때 "이전 버튼"을 클릭하면 let musicindex의 값을 음악의 총 길이로 바꿉니다.
  • loadMusic()한테 let musicIndex의 값을 전달합니다.
  • playMusic()함수를 실행합니다

4. nextMusic() 익명 함수

  • let musicIndex의 값이 음악의 총길이일때 "다음 버튼"을 클릭하면 let musicindex의 값을 1로 바꿉니다.
  • loadMusic()한테 let musicIndex의 값을 전달합니다.
  • playMusic()함수를 실행합니다.

5.

// 뮤직 진행바
musicAudio.addEventListener("timeupdate", e => {
    // console.log(e);

    const currentTime = e.target.currentTime;   //현재 재생 시간
    const duration = e.target.duration;         //오디오의 총 길이
    let progrossWidth = (currentTime/duration) * 100; //전체 길이에서 현재 진행되는 시간을 백분위 단위로 나누면 현재 진행상태를 알수 있음

    musicPregressBar.style.width = `${progrossWidth}%`;

    // 전체 시간
    musicAudio.addEventListener("loadeddata", () => {
        let audioDuration = musicAudio.duration;
        let totalMin = Math.floor(audioDuration / 60);
        let totalSec = Math.floor(audioDuration % 60);

        if(totalMin < 10) totalMin = `0${totalMin}`;
        if(totalSec < 10) totalSec = `0${totalSec}`;

        musicProgressDuration.innerText = `${totalMin}:${totalSec}`;        
    });

    // 진행 시간
    let currentMin = Math.floor(currentTime / 60);
    let currentSec = Math.floor(currentTime % 60);

    if(currentMin < 10) currentMin = `0${currentMin}`;
    if(currentSec < 10) currentSec = `0${currentSec}`;

    musicProgressCurrent.innerText = `${currentMin}:${currentSec}`;
});
  • 해당 코드는 HTML 오디오 태그를 이용하여 음악을 재생할 때,
  • 현재 음악이 얼마나 재생되고 있는지 진행바와 함께 보여주는 기능을 구현하는 코드입니다.
  • 이 코드에서 "timeupdate" 이벤트가 발생하면, 현재 재생되고 있는
  • 음악의 현재 시간과 총 길이를 가져와서 현재 음악이 얼마나 진행되었는지 계산합니다.
  • 이 값을 이용하여 프로그레스 바의 길이를 조정하고, 현재 음악의 진행 시간과 전체 시간을 계산하여 화면에 출력합니다.
  • 따라서 해당 코드는 음악 재생 시, 현재 음악의 재생 상태를 시각적으로 보여주는 역할을 합니다.

6.

// 진행 버튼 클릭
musicPregress.addEventListener("click", (e) => {
    let progressWidth = musicPregress.clientWidth;  //진행바 전체 길이
    let clickOffsetX = e.offsetX;                   //진행바를 기준으로 측정되는 X값 좌펴
    let songDuration = musicAudio.duration;          //오디오 전체 길이
    //백분위로 나눈 숫자에 다시 전체 길이를 곱해 현재 재생값으로 바꿈
    musicAudio.currentTime = (clickOffsetX /progressWidth) * songDuration;
});

querySelector(".progress")를 클릭했으면 해당 음악의 값을 구해옵니다.

clientWidth 요소의 콘텐츠 영역의 너비를 반환하는 속성 입니다
offsetX 마우스 이벤트(mouse event)에서 해당 이벤트가 발생한 요소(element)의 상대적인 X 좌표값을 반환 속성입니다.
duration 미디어(media) 요소의 총 재생 시간을 나타내는 속성입니다.

 

7.

// 플레이 클릭
musicPlay.addEventListener("click", () => {
    // "" : 빈 문자열은 "거짓"임
    const isMusicPaused = musicWrap.classList.contains("paused");   //음악 재생 중
    isMusicPaused ? pauseMusci() : playMusic();

    // playMusic();
});
  • querySelector("#control-play")를 클릭하고 querySelector(".music__wrap");에 
  • paused 클래스가 있으면 pauseMusci() 함수를 실행합니다. 
  • paused 클래스가 없으면 playMusci() 함수를 실행합니다. 

 

8.

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

// 다음곡 클릭
musicNextBtn.addEventListener("click", () => {
    nextMusic();
});
  • querySelector("#control-prev");를 클릭했으면 prevMusic() 함수를 실행합니다.
  • querySelector("#control-next");를 클릭했으면 nextMusic() 함수를 실행합니다.