결과
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
안에innerText
로song
을 담는다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
가 추가되고
재생이 되면 재생 플레이버튼이 리무브되고 정지 버튼 클래스가 추가된다.
그러고 나서audio
는play();
가 된다.- 정지
함수pauseSong
이 동작되면musicContainer
에 클래스.play
가 제거되고 마찬가지로 정지버튼이 리무브되고 재생 버튼 클래스가 추가된다.
그러고 나서audio
는pause();
가 된다.
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.width
를progressPercent
값을 넣어준다.
#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
=this
의clientWidth
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
재생
이 되게 한다.