“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”
- Frederick Philips Brooks
Mythical Man-Month 저자
자바스크립트 게임 이펙트 _음악 재생
💜 게임 이펙트
HTML
<!-- 뮤직 플레이어 -->
<div class="music__wrap">
<div class="music__inner">
<div class="music__header">
<span class="left"></span>
<h2>music</h2>
<span class="right"></span>
</div>
<div class="music__contents">
<div class="music__view">
<div class="image">
<img src="../game/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="currnet">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>
<!-- //뮤직 플레이어 -->
뮤직 플레이어 구역을 추가해줬습니다.
js
const allMusic = [
{
name: "1. Who Do You Think I Think You Are",
artist: "Mini Vandals",
img: "music_view01",
audio: "music_audio01"
}, {
name: "2. The Monuments and Tunnels in Goa and Hampi",
artist: "Bail Bonds",
img: "music_view02",
audio: "music_audio02"
}, {
name: "3. We Cruisin'",
artist: "Otis McDonald",
img: "music_view03",
audio: "music_audio03"
}, {
name: "4. Forever Young",
artist: "Otis McDonald",
img: "music_view04",
audio: "music_audio04"
}, {
name: "5. Ice & Fire",
artist: "King Canyon",
img: "music_view05",
audio: "music_audio05"
}, {
name: "6. Emotional Mess",
artist: "Amy Lynn & the Honey Men",
img: "music_view06",
audio: "music_audio06"
}, {
name: "7. The Last Goodbye",
artist: "Telecasted",
img: "music_view07",
audio: "music_audio07"
}, {
name: "8. Big River",
artist: "Telecasted",
img: "music_view08",
audio: "music_audio08"
}, {
name: "9. The Urban Groove",
artist: "Hanu Dixit",
img: "music_view09",
audio: "music_audio09"
}, {
name: "10. The Monuments and Tunnels in Goa and Hampi",
artist: "Bail Bonds",
img: "music_view10",
audio: "music_audio10"
}
];
music.js파일을 따로 만들어 작업했습니다.
노래제목과 아티스트, 이미지, 음악을 배열로 저장해줬습니다.
선택자
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 musicProgressBar = musicWrap.querySelector(".progress .bar");
const musicProgress = musicWrap.querySelector(".progress");
const musicProgressCurrent = musicWrap.querySelector(".progress .timer .currnet");
const musicProgressDuration = musicWrap.querySelector(".progress .timer .duration");
사용할 선택자를 하나씩 만들어줬습니다.
음악 재생 , 정지 , 이전, 다음
let musicIndex = 1; //현재 음악 인덱스
//음악 재생
const loadMusic = (num) => {
musicName.innerText = allMusic[num-1].name; //뮤직 이름
musicArtist.innerText = allMusic[num-1].artist; //아티스트 이름
musicView.src = `../game/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 == 1 ? musicIndex = allMusic.length : musicIndex--;
loadMusic(musicIndex);
playMusic();
}
//다음 곡 듣기
const nextMusic = () => {
//1 2 3 4 5 6 7 8 9 1
// musicIndex++;
// if(musicIndex == 9) musicIndex == 1;
musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
loadMusic(musicIndex);
playMusic();
}
//진행 버튼 클릭
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);
});
loadMusic 함수 : 해당 번호에 해당하는 음악 정보를 로드하고, 텍스트 이미지 및 오디오 파일을 해당 정보와 일치하도록 설정합니다.
playMusic 함수 : 음악 재생 버튼이 클릭되면, 해당 클래스를 추가해 재생 버튼을 일시 중지 버튼으로 변경하고
musicAudio.paly()함수를 호출해 음악을 재생합니다.
pauseMusic 함수 : 일시 중지 버튼이 클릭되면, 해당 클래스를 제거하여 일시 중지 버튼을 재생 버튼으로 변경하고, musicAudi.pause()를 호출해 음악을 일시 중지 합니다.
prevMusic 함수 : 이전 곡 버튼이 클릭되면, musicIndex 를 감소히켜 이전 곡을 로드하고, loadMusic 및 playMusic 함수를 호출해 해당 음악을 재생합니다.
nextMusic 함수 : 다음 곡 버튼이 클릭되면, musicIndex 를 증가시켜 다음 곡을 로드하고 loadMusic 및 playMusic함수를 호출하여 해당 음악을 재생합니다.
musicProgress 이벤트 리스너 : 사용자가 진행 바를 클릭하면, 클릭된 위치의 X 좌표를 측정하고, 전체 길이를 나눈 후, 이를 현재 재생 값으로 변환해 musicAudio.cureentTime값을 설정합니다.
musicPlay, musicPrevBtn, musicNextBtn 이벤트 리스너: 해당 버튼이 클릭되면, isMusicPaused변수를 사용해 음악이 현재 일시 중지 중인지 확인하고, pauseMusic 또는 palyMusic 함수를 호출해 해당 동작을 수행합니다.
window , load 이벤트 리스너: 웹 페이지가 로드될 때, 첫 번째 음악을 로드하고 재생을 시작합니다.
//뮤직 진행바
musicAudio.addEventListener("timeupdate", e => {
console.log(e);
const currentTime = e.target.currentTime; // 현재 재생되는 시간
const duration = e.target.duration; //오디오의 총 길이
let progrssWidth = (currentTime/duration) * 100; //전체 길이에서 현재 진행되는 시간을 백분위로 나누면
// console.log(progrssWidth);
musicProgressBar.style.width = `${progrssWidth}%`;
// 전체 시간
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}`;
});
musicAidio 변수는 HTML 의 audio요소입니다.
이 요소에 timeupdate 이벤트가 발생하면 e 객체를 전달받습니다.
e.target.currentTime 은 현재 재생되고 있는 뮤직 파일의 시간을 나태냅ㄴ디ㅏ.
e.target.duration 은 뮤직 파일의 총 길이를 나타냅니다.
이 정보를 사용해 progressWidth 변수에 현재 뮤직 파일의 재생 시간이 총 길이에 대한 백분율로 계산됩니다.
이 값을 musicProgressBar요소의 너비로 설정해 뮤직 플레이어UI의 진행바를 업데이트 합니다.
loadeddata 이벤트를 사용해 뮤직 파일의 전체 길이를 가져와 totalMin과 totalSec 변수에 저장,
이 값을 사용해 musicProgressDuration 요소에 뮤직 파일의 전체 시간을 업데이트 합니다.
currentMin 과 currentSec 변수에 현재 뮤직 파일의 재생 시간을 분:초 형식으로 계산하고, 이 값을 사용해 musicProgressCurrent 요소에 뮤직 파일의 현재 시간을 업데이트 합니다.