JavaScript

뮤직플레이어 만들기

결과

HTML

<body>
    <h1>Music Player</h1>
    <div class="music-container" id="music-container">
        <div class="music-info">
            <h4 id="title"></h4>
            <div class="progress-container" id="progress-container">
                <div class="progress" id="progress"></div>
            </div>
        </div>
        <audio src="./music/hey.mp3" id="audio"></audio>
        <div class="img-container">
            <img src="./images/hey.jpg" alt="music-cover" id="cover">
        </div>
        <div class="navigation">
            <button id="prev" class="action-btn">
                <i class="fas fa-backward"></i>
            </button>
            <button id="play" class="action-btn action-btn-big">
                <i class="fas fa-play"></i>
            </button>
            <button id="next" class="action-btn">
                <i class="fas fa-forward"></i>
            </button>
        </div>
    </div>
</body>

CSS

*{margin: 0; padding: 0; box-sizing: border-box;}
body{
    background-image: linear-gradient(0deg, rgba(247,247,247,1) 23%, rgba(252,221,221,1) 92%);
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}
.music-container{
    background: #fff;
    border-radius: 15px;
    box-shadow: 0 20px 20px 0 rgba(255, 169, 169, .6);
    display: flex;
    padding: 20px 30px;
    position: relative;
    margin: 100px 0;
    z-index: 10;
}
.music-info{
    background-color: rgba(255, 255, 255, .5);
    border-radius: 15px 15px 0 0;
    position: absolute;
    top: 0;
    left: 20px;
    width: 360px/* calc(100%-40px) */;
    padding: 10px 10px 10px 150px;
    opacity: 0;
    transform: translateY(0%);
    transition: transform .3s ease-in, opacity .3s ease-in;
}
.music-container.play .music-info{
    opacity: 1;
    transform: translateY(-100%);
}
.progress-container{
    background: #fff;
    border-radius: 5px;
    cursor: pointer;
    width: 100%;
    height: 4px;
    margin: 10px 0;
    /* position: absolute; */
}
.progress{
    background: #000;
    width: 100%;
    height: 100%;
    border-radius: 5px;
    transition: width .1s linear;
    /* cursor: move; */
}
.img-container{position: relative; width: 110px;}
.img-container img{
    position: absolute;
    border-radius: 50%;
    height: 110px;
    width: 100%;
    object-fit: cover;
    bottom: 0;
    left: 0;
    animation: rotate 3s linear infinite;
    animation-play-state: paused;
}
.music-container.play .img-container img{
    animation-play-state: running;
}
@keyframes rotate {
    from{transform: rotate(0deg);}
    to{transform: rotate(360deg);}
}
.navigation{
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
}
.action-btn{
    font-size: 30px;
    color: #cdc2d0;
    background-color: #fff;
    border: 0;
    cursor: pointer;
    padding: 10px;
    margin: 0 20px;
}
.action-btn.action-btn-big{
    font-size: 30px;
    color: rgb(133, 130, 130);
}
.action-btn:focus{
    outline: 0;
}

script

const musicContainer=document.getElementById('music-container');
const playBtn=document.getElementById('play');
const prevBtn=document.getElementById('prev');
const nextBtn=document.getElementById('next');
const audio=document.getElementById('audio');
const progress=document.getElementById('progress');
const progressContainer=document.getElementById('progress-container');
const title=document.getElementById('title');
const cover=document.getElementById('cover');
const songs=['hey','summer','ukulele']
let songIndex=2;
loadsong(songs[songIndex]);
function loadsong(song){
    title.innerText=song;
    audio.src=`music/${song}.mp3`
    cover.src=`images/${song}.jpg`
}
//play
function playSong(){
    musicContainer.classList.add('play');
    playBtn.querySelector('i.fas').classList.remove('fa-play');
    playBtn.querySelector('i.fas').classList.add('fa-pause');
    audio.play();
}
//pause
function pauseSong(){
    musicContainer.classList.remove('play');
    playBtn.querySelector('i.fas').classList.add('fa-play');
    playBtn.querySelector('i.fas').classList.remove('fa-pause');
    audio.pause();
}
playBtn.addEventListener('click', ()=>{
    const isPlaying=musicContainer.classList.contains('play');
    if(isPlaying){
        pauseSong();
    }else{
        playSong();
    }
});
//prev 재생 , next 재생
function prevSong(){
    songIndex--;
    if(songIndex < 0){songs.length-1;}
    loadsong(songs[songIndex]);
    playSong();
}
function nextSong(){
    songIndex++;
    if(songIndex > songs.length-1){songIndex=0;}
    loadsong(songs[songIndex]);
    playSong();
}
//progress bar 
function updateProgress(e){
    const{duration, currentTime} = e.srcElement;
    const preogressPercent=(currentTime/duration)*100;
	progress.style.width=`${preogressPercent}%`;
}
//progress bar moving
function setProgress(e){
    const width=this.clientWidth;
    const clickX=e.offsetX;
    const duration=audio.duration;
	audio.currentTime=(clickX/width)*duration;
}
audio.addEventListener('timeupdate',updateProgress)
progressContainer.addEventListener('click',setProgress);
//prev 버튼 , next 버튼
nextBtn.addEventListener('click',nextSong)
prevBtn.addEventListener('click',prevSong)
//실제 재생이 끝까지 된다면 다음곡이 재생
audio.addEventListener('ended',nextSong);

#Script 01

const musicContainer=document.getElementById('music-container');
const playBtn=document.getElementById('play');
const prevBtn=document.getElementById('prev');
const nextBtn=document.getElementById('next');
const audio=document.getElementById('audio');
const progress=document.getElementById('progress');
const progressContainer=document.getElementById('progress-container');
const title=document.getElementById('title');
const cover=document.getElementById('cover');
const songs=['hey','summer','ukulele']
let songIndex=2;

변수는 각 HTML에 선택자를 선택한 변수이며 노래는 변수 songs 안에 배열 ['hey' , 'summer' , 'ukulele']로 담았다. songIndex는 배열 0, 1, 2 총 3개 이므로 2를 담았다.


#Script 02

loadsong(songs[songIndex]);
function loadsong(song){
    title.innerText=song;
    audio.src=`music/${song}.mp3`
    cover.src=`images/${song}.jpg`
}

함수 loadsong 을 만든다.

  • title안에 innerTextsong을 담는다
  • audio.src : 경로는 index.html기준으로 music/${song}.mp3
  • cover.src : 앨범 커버 이미지의 경로도 index.html기준으로 images/${song}.jpg

#Script 03

//play
function playSong(){
    musicContainer.classList.add('play');
    playBtn.querySelector('i.fas').classList.remove('fa-play');
    playBtn.querySelector('i.fas').classList.add('fa-pause');
    audio.play(); //javascript에서는 play이고 jquery에서는 ??
}
//pause
function pauseSong(){
    musicContainer.classList.remove('play');
    //<i class="fas fa-pause"></i>
    playBtn.querySelector('i.fas').classList.add('fa-play');
    playBtn.querySelector('i.fas').classList.remove('fa-pause');
    audio.pause();
}
playBtn.addEventListener('click', ()=>{
    const isPlaying=musicContainer.classList.contains('play');
    if(isPlaying){
        pauseSong();
    }else{
        playSong();
    }
});

재생 (play) , 정지(pause)를 동작시키는 스크립트이다.

  • 재생
    함수 playSong 이 동작되면 musicContainer에 클래스 .play가 추가되고
    재생이 되면 재생 플레이버튼이 리무브되고 정지 버튼 클래스가 추가된다.
    그러고 나서 audioplay();가 된다.
  • 정지
    함수 pauseSong 이 동작되면 musicContainer에 클래스 .play가 제거되고 마찬가지로 정지버튼이 리무브되고 재생 버튼 클래스가 추가된다.
    그러고 나서 audiopause();가 된다.

playBtn에 클릭 이벤트를 실행시키는데, musicContainer에 클래스 play가 있다면 pauseSong() 진행되고 없다면 playSong() 이 된다.


#Script 04

//prev 재생 , next 재생
function prevSong(){
    songIndex--;
    if(songIndex < 0){songIndex=2;}//늘어난다고 생각하면 songs.length-1
    loadsong(songs[songIndex]);
    playSong();
}
function nextSong(){
    songIndex++;
    if(songIndex > songs.length-1){songIndex=0;}
    loadsong(songs[songIndex]);
    playSong();
}

prev 버튼 , next 버튼을 누르면 다음곡 , 이전곡 재생이 되는 스크립트이다.

  • prev 버튼
    함수 prevSong 이 동작되면 songIndex가 -1 이 되고 if 조건문 0 즉 첫번째 곡의 인덱스 넘버보다 작을경우 songIndex가 3번째 곡으로 돌아가고 노래가 재생이된다.
  • next 버튼
    함수 nextSong 이 동작되면 songIndex가 +1 이 되고 if 조건문 노래의 배열 인덱스 값이 노래 배열보다 크게 된다면 songIndex는 첫번째 곡으로 돌아간다.

#Script 05

//progress bar 
function updateProgress(e){
    const{duration, currentTime} = e.srcElement;
    const preogressPercent=(currentTime/duration)*100;
	progress.style.width=`${preogressPercent}%`;
}

재생이 되고 있는 노래의 구간을 나타내는 프로그레스바이다.
함수 updateProgress 안에 구조 분해 할당 변수를 담는다.

const{duration, currentTime} = e.srcElement;

그러고 아래의 프로그래스바의 퍼센트를 계산하여 현재 위치를 나타나게 하기 위해 현재 재생되고있는 시간과 총 길이 나누기 100 을 하여 % 를 구한다.

const progressPercent=(currentTime/duration)*100;

그 값을 프로그레스바의 css.style.widthprogressPercent 값을 넣어준다.


#Script 06

//progress bar moving
function setProgress(e){
    const width=this.clientWidth;
    const clickX=e.offsetX;
    const duration=audio.duration;
	audio.currentTime=(clickX/width)*duration;
}
audio.addEventListener('timeupdate',updateProgress)
progressContainer.addEventListener('click',setProgress);
//prev 버튼 , next 버튼
nextBtn.addEventListener('click',nextSong)
prevBtn.addEventListener('click',prevSong)
//실제 재생이 끝까지 된다면 다음곡이 재생
audio.addEventListener('ended',nextSong);

함수 setProgress 안에
width = thisclientWidth
clickX = e.offsetX
duration = audio 의 duration
audio의 currentTime = clickX (e.offsetX) / clientWidth * audio의 duration을 만든다.
audio의 timeupdate 이벤트를 하면 updateProgress 한다.
progresssContainer 클릭 이벤트를 하면 setProgress 를 한다.

나머지

nextBtn.addEventListener('click',nextSong)
prevBtn.addEventListener('click',prevSong)
//실제 재생이 끝까지 된다면 다음곡이 재생
audio.addEventListener('ended',nextSong);
  • nextBtn 클릭 하면 nextSong
  • prevBtn 클릭 하면 prevSong
  • audio의 재생이 ended 끝나면 nextSong 재생
    이 되게 한다.

0개의 댓글