게임 효과
게임 이펙트 - 음악플레이어
오늘은 audio태그를 이용해서 음악플레이어를 만들어보겠습니다.
결과
HTML 작성
전체 틀을 헤더와 메인 푸터로 잡아주고 음악플레이어틀을 잡아줍니다.
소스 보기
<header id="header">
<h1>Game shop</h1>
<div class="time"></div>
</header>
<!-- //header -->
<div class="cursor">
<img src="../assets/img/cursor.png" alt="커서">
</div>
<main id="main">
<div class="icon_box">
<div class="icon1">
<img src="../assets/img/icon1.png" alt="아이콘">
<span>음악듣기</span>
</div>
<div class="icon2">
<img src="../assets/img/icon2.png" alt="아이콘">
<span>음악듣기</span>
</div>
<div class="icon3">
<img src="../assets/img/icon3.png" alt="아이콘">
<span>음악듣기</span>
</div>
<div class="icon4">
<img src="../assets/img/icon4.png" alt="아이콘">
<span>음악듣기</span>
</div>
<div class="icon5">
<img src="../assets/img/icon5.png" alt="아이콘">
<span>음악듣기</span>
</div>
<div class="icon6">
<img src="../assets/img/icon6.png" alt="아이콘">
<span>음악듣기</span>
</div>
</div>
</main>
<!-- //main -->
<!-- 뮤직 플레이어 -->
<div class="music__wrap">
<div class="music__inner">
<div class="music__header">
<div>***</div>
<h2>Music player</h2>
<div>***</div>
</div>
<div class="music__contents">
<img class="volume_icon" src="../assets/img/volume.svg" alt="볼륨" />
<img class="volumeOff_icon" src="../assets/img/volumeoff.svg" alt="볼륨" />
<div class="volume_bar">
<input type="range" id="volume-control" min="0" max="10" />
</div>
<div class="music__view">
<div class="img">
<img src="../assets/img/img01.png" alt="">
</div>
<div class="title">
<h3>Cottonmouth -</h3>
<p>YouTube Music</p>
</div>
</div>
<div class="music__control">
<div class="progress">
<div class="bar">
<audio id="main-audio" src="../assets/audio/music_audio01.mp3"></audio>
</div>
<div class="timer">
<span class="current">0:00</span>
<span class="duration">4:00</span>
</div>
</div>
<div class="control">
<i title="전체 반복" class="repeat" id="control-repeat"></i>
<!-- <i title="한곡 반복" class="repeat_one"></i> -->
<!-- <i title="랜덤 반복" class="shuffle"></i> -->
<i title="이전곡 재생" class="prev" id="control-prev"></i>
<i title="재생" class="play" id="control-play"></i>
<!-- <i title="정지" class="stop"></i> -->
<i title="다음곡 재생" class="next" id="control-next"></i>
<i title="재생 목록" class="list" id="control-list"></i>
</div>
</div>
</div>
<div class="music__footer">
<div class="music__list">
<h3><span class="list"></span>뮤직 리스트<span class="close_btn"></span></h3>
<ul>
<!-- <li>
<strong>제목</strong>
<em>아티스트</em>
<span>재생시간</span>
</li> -->
</ul>
</div>
</div>
</div>
</div>
<!-- //뮤직 플레이어 -->
CSS 작성
헤더와 푸터, 소스보기 CSS
소스 보기
@import url("https://webfontworld.github.io/sandbox/SBAggro.css");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "SBAggro";
cursor: none !important;
}
body {
width: 100%;
height: 100vh;
overflow: hidden;
}
/* scroll */
::-webkit-scrollbar {
width: 8px;
height: 10px;
}
::-webkit-scrollbar-track {
background: rgb(9, 77, 159, 0.4);
}
::-webkit-scrollbar-thumb {
background: #094d9f;
border-radius: 20px;
}
#header {
position: fixed;
width: 100%;
height: 35px;
background-color: #094d9f;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
}
#header h1 {
font-size: 20px;
color: #fff;
padding: 5px 0;
}
#header .time {
color: #fff;
transform: translateY(1px);
}
#footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 35px;
background-color: #000;
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 10px;
color: #fff;
text-align: center;
}
.icon_box img {
width: 100%;
}
.icon_box span {
text-align: center;
display: block;
background: #000;
border-radius: 5px;
color: yellow;
font-size: 14px;
padding: 2px;
white-space: nowrap;
}
.icon1 {
position: absolute;
left: 100px;
top: 100px;
width: 60px;
}
.icon2 {
position: absolute;
left: 100px;
top: 200px;
width: 60px;
}
.icon3 {
position: absolute;
left: 100px;
top: 300px;
width: 60px;
}
.icon4 {
position: absolute;
left: 100px;
top: 400px;
width: 60px;
}
.icon5 {
position: absolute;
left: 100px;
top: 500px;
width: 60px;
}
.icon6 {
position: absolute;
left: 100px;
top: 600px;
width: 60px;
}
/* 커서 */
.cursor {
position: absolute;
left: 0;
top: 0;
width: 50px;
height: 50px;
z-index: 1;
pointer-events: none;
user-select: none;
}
.cursor img {
width: 15px;
}
/* window */
.mac #footer {
background: #09989f;
}
.window #footer {
background: #094d9f;
}
/* modal__wrap */
.modal__btn {
color: #fff;
border: 1px solid #fff;
border-radius: 50px;
display: inline-block;
padding: 10px 20px;
position: absolute;
right: 20px;
bottom: 40px;
cursor: pointer;
transition: background-color 0.3s, color 0.3s;
}
.modal__btn:hover {
background-color: #fff;
color: #3b3d63;
}
.modal__btn label:hover {
cursor: pointer;
}
.modal__cont {
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
left: 0;
top: 0;
overflow-x: hidden;
display: flex;
align-items: center;
justify-content: center;
transform: scale(0);
}
.modal__box {
width: 70%;
height: 80vh;
border-radius: 0.6rem;
box-shadow: 0 10px 20px -5px hsl(180deg 2% 10%);
transform: scale(0);
}
.modal__box .title {
padding-inline: 1rem;
background-color: #1b1c2e;
display: flex;
align-items: center;
color: #fff;
height: 50px;
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.modal__box .title .dot {
width: 15px;
height: 15px;
background-color: #3b3d63;
display: inline-block;
border-radius: 50%;
position: relative;
margin-left: 2rem;
}
.modal__box .title .dot::before {
content: "";
position: absolute;
left: 25px;
top: 0;
width: 15px;
height: 15px;
background-color: #3b3d63;
border-radius: 50%;
}
.modal__box .title .dot::after {
content: "";
position: absolute;
right: 25px;
top: 0;
width: 15px;
height: 15px;
background-color: #3b3d63;
border-radius: 50%;
}
.modal__box .title .plus {
background: #282936;
padding: 0.5rem 0.5rem 0.3rem 0.5rem;
border-radius: 0.5rem;
color: #7a7d9d;
}
.modal__box .title .tabs {
display: flex;
margin-left: 50px;
}
.modal__box .title .tabs > div {
color: #7a7d9d;
background-color: #282936;
padding: 0.35rem 0.8rem 0.25rem 0.8rem;
margin-right: 0.5rem;
display: flex;
align-items: center;
border-radius: 0.4rem;
text-transform: uppercase;
cursor: pointer;
}
.modal__box .title .tabs > div.active {
background-color: #1f224a;
}
.modal__box .title .tabs > div em {
font-style: normal;
}
.modal__box .title .tabs > div .favicon {
margin-right: 0.4rem;
margin-top: 0.2rem;
}
.modal__box .title .tabs > div .close {
margin-left: 4rem;
}
.modal__box .cont {
background-color: #282936;
height: 100%;
overflow-y: auto;
box-sizing: border-box;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}
.modal__box .cont > div {
display: none;
height: 100%;
}
.modal__box .cont > div.active {
display: block;
height: 100%;
}
.modal__close {
position: absolute;
right: 20px;
top: 20px;
background-color: #1f224a;
padding: 1rem 1rem 0.8rem 1rem;
border-radius: 5px;
box-shadow: 0 5px 7px -5px rgba(25, 26, 26, 0.698);
cursor: pointer;
transition: all 0.3s;
opacity: 0;
}
.modal__close:hover {
background-color: #33377d;
}
.modal__close svg {
color: #fff;
}
/* 모달 애니메이션 */
.modal__cont.show {
/* 전체 배경 */
animation: foldOut 1s ease forwards;
}
.modal__cont.show .modal__box {
/* 스크립트 박스 */
animation: zoomOut 0.5s 1s ease forwards;
}
.modal__cont.show .modal__close {
/* 닫기 버튼 */
animation: opacityOut 0.5s 1.5s ease forwards;
}
.modal__cont.show.hide {
animation: foldIn 0.3s 0.5s ease backwards;
}
.modal__cont.show.hide .modal__box {
animation: zoomIn 0.5s ease forwards;
}
.modal__cont.show.hide .modal__close {
animation: opacityIn 0.8s ease forwards;
}
@keyframes foldOut {
0% {
transform: scaleX(0) scaleY(0.001);
}
50% {
transform: scaleX(1) scaleY(0.001);
}
100% {
transform: scaleX(1) scaleY(1);
}
}
@keyframes foldIn {
0% {
transform: scaleX(1) scaleY(1);
}
50% {
transform: scaleX(1) scaleY(0.001);
}
100% {
transform: scaleX(0) scaleY(0.001);
}
}
@keyframes zoomOut {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes zoomIn {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes opacityOut {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes opacityIn {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@media (max-width: 1100px) {
.modal__box .title {
overflow: hidden;
}
.modal__box .title .dot {
display: none;
}
.modal__box .title .tabs {
margin-left: 0;
}
.modal__box .title .tabs > div .close {
display: none;
}
}
@media (max-width: 800px) {
#header {
width: 100%;
text-align: center;
}
#header h1 {
line-height: 1.4;
}
.modal__box {
width: 96%;
}
}
뮤직플레이어 CSS
소스 보기
@import url("https://webfontworld.github.io/earlyfont/EF_Macho.css");
.music__wrap {
}
.music__inner {
width: 450px;
background: #000;
position: absolute;
right: 100px;
top: 100px;
padding: 10px;
padding-top: 0;
}
.music__header {
width: 100%;
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
color: #fff;
}
.music__header h2 {
font-size: 14px;
}
.music__contents {
background: #c4c4c4;
width: 100%;
}
.music__contents .volume_icon {
position: absolute;
top: 39px;
right: 130px;
}
.music__contents .volumeOff_icon {
display: none;
position: absolute;
top: 39px;
right: 130px;
}
.music__contents .volume_icon.hide {
display: none;
position: absolute;
top: 39px;
right: 130px;
}
.music__contents .volumeOff_icon.show {
display: block;
position: absolute;
top: 39px;
right: 130px;
}
.music__contents .volume_bar {
position: absolute;
right: 0px;
top: 30px;
}
.music__view {
display: flex;
padding: 20px;
}
.music__view .img {
width: 30%;
}
.music__view .img img {
width: 100%;
}
.music__view .volume {
margin-top: 5px;
width: 80%;
height: 6px;
background: #000;
border-radius: 5px;
}
.music__view .title {
width: 69%;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.music__view .title h3 {
margin-bottom: 5px;
font-size: 20px;
line-height: 1.2;
}
.music__view .title p {
color: #094d9f;
}
.music__control {
width: 100%;
height: 100px;
padding: 20px;
padding-top: 0;
}
.music__control .control i:hover {
background-color: #fff;
border-radius: 5px;
padding: 10px;
/* transition: all 0.6s; */
}
.music__control .progress {
width: 100%;
height: 6px;
background: #000;
border-radius: 5px;
}
.music__control .progress .bar {
width: 0;
height: inherit;
background: #7fff58;
border-radius: 5px;
}
.music__control .progress .timer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 3px;
}
.music__control .control {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 40px;
}
.music__control .control .repeat {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -288px 0;
transform: scale(0.8);
}
.music__control .control .repeat-one {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -336px 0;
transform: scale(0.8);
}
.music__control .control .shuffle {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -240px 0;
transform: scale(0.8);
}
.music__control .control .prev {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -96px 0;
transform: scale(0.8);
}
.music__control .control .play {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: 0 0;
transform: scale(0.8);
}
.music__control .control .stop {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -48px 0;
transform: scale(0.8);
}
.music__control .control .next {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -144px 0;
transform: scale(0.8);
}
.music__control .control .list {
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -192px 0;
transform: scale(0.8);
}
.music__footer {
background: #c4c4c4;
}
.music__list {
display: none;
padding: 20px;
}
.music__list.show {
display: block;
}
.music__list ul {
max-height: 200px;
overflow-y: scroll;
padding-right: 10px;
}
.music__list h3 {
font-size: 24px;
margin-bottom: 10px;
padding-top: 10px;
border-top: 2px solid #000;
}
.music__list h3 .list {
display: inline-block;
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -192px 0;
transform: scale(0.8);
margin-right: 5px;
vertical-align: -14px;
}
.music__list h3 .close_btn {
display: inline-block;
width: 48px;
height: 48px;
background: url(../img/music_icon.svg);
background-position: -384px 0;
transform: scale(0.8);
float: right;
vertical-align: -14px;
}
.music__list h3 .close_btn:hover {
background-color: #fff;
padding: 10px;
border-radius: 5px;
transition: all 0.6s;
}
.music__list li {
border-bottom: 1px solid #000;
list-style: none;
position: relative;
padding: 7px 0 5px;
}
.music__list li.playing {
color: #094d9f;
}
.music__list li strong {
display: block;
font-size: 16px;
}
.music__list li em {
font-style: normal;
}
.music__list li span {
position: absolute;
right: 0;
top: 25px;
}
/* 볼륨 조절 버튼 */
input[type=range] {
font-size: 16px;
box-sizing: border-box;
height: 2em;
width:80%;
-webkit-appearance: none;
background: transparent;
}
/* input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type="range"]:focus {
outline: none;
} */
input[type="range"]::-ms-track {
width: 100%;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: .5em;
height: 1em;
margin-top: 2.5px;
background-color: rgb(9, 77, 159, 0.5);
border: 2px solid #094d9f;
}
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
width: .5em;
height: 1em;
margin-top: 2.5px;
background-color: rgb(9, 77, 159, 0.5);
border: 2px solid #094d9f;
}
input[type="range"]::-ms-thumb {
-webkit-appearance: none;
width: .5em;
height: 1em;
margin-top: 2.5px;
background-color: rgb(9, 77, 159, 0.5);
border: 2px solid #094d9f;
}
input[type="range"]:hover::-webkit-slider-thumb {
background-color: rgba(7, 49, 100, 0.8);
}
input[type="range"]:hover::-moz-range-thumb {
background-color: rgba(7, 49, 100, 0.8);
}
input[type="range"]:hover::-ms-thumb {
background-color: rgba(7, 49, 100, 0.8);
}
input[type="range"]:active::-webkit-slider-thumb {
border-color: #ffffff76;
}
input[type="range"]:active::-moz-range-thumb {
border-color: #ffffff76;
}
input[type="range"]:active::-ms-thumb {
border-color: #ffffff76;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: .7em;
border-bottom: 2px solid rgba(255, 255, 255, 0.5);
background-color: transparent;
}
input[type="range"]::-moz-range-track {
width: 100%;
height: .7em;
border-bottom: 2px solid rgba(255, 255, 255, 0.5);
background-color: transparent;
}
input[type="range"]::-ms-track {
background: transparent;
border-color: transparent;
color: transparent;
}
JS 작성
마우스 드래그 스크립트
마우스로 드래그할수 있도록 하는 스크립트입니다. 제이쿼리홈페이지에서 가져옵시다. 확장자 파일은 src로 사용합니다.
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<script>
const cursor = document.querySelector(".cursor");
window.addEventListener("mousemove" , e => {
gsap.to(cursor, {duration: 0, left: e.pageX -1, top: e.pageY -3})
})
$( function() {
$(".icon1").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor.png")
},
});
$(".icon2").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor2.png")
},
});
$(".icon3").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor3.png")
},
});
$(".icon4").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor4.png")
},
});
$(".icon5").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor5.png")
},
});
$(".icon6").draggable({
drag: function() {
$(".cursor img").attr("src", "../assets/img/cursor6.png")
},
});
$(".music__wrap").draggable({
});
} );
</script>
날짜와 현재 시각
각 메서드들을 이용해 현재의 시, 분, 초를 불러오고, setTimeout함수로 1초마다 계속 실행시켜줍니다. 운영체제와, 화면의 크기도 메서드로 구해줍니다. 그리고 만들어진 함수를 윈도우가 켜지면 바로 실행되도록 실행시켜줍니다.
<script>
function printTime(){
const clock = document.querySelector(".time");
const now = new Date();
let nowHours = now.getHours();
let nowMinutes = now.getMinutes();
let nowSeconds = now.getSeconds();
if(nowHours > 12) nowHours = `0${nowHours - 12}`;
if(nowMinutes < 10) nowMinutes = `0${nowMinutes}`;
if(nowSeconds < 10) nowSeconds = `0${nowSeconds}`;
const nowTime = `오늘은 ${now.getFullYear()} 년 ${now.getMonth() + 1} 월 ${now.getDate()}일 ${nowHours} 시 ${nowMinutes}분 ${nowSeconds}초 입니다.`;
clock.innerText = nowTime;
setTimeout("printTime()", 1000);
}
function printAgent(){
const agent = document.querySelector(".agent");
const os = navigator.userAgent.toLocaleLowerCase();
if(os.indexOf("window") >= 0){
agent.innerText = "현재 윈도우를 사용하고 화면 크기는 " + screen.width + " *" + screen.height + "입니다.";
document.querySelector("body").classList.add("window");
} else if (os.indexOf("macintosh" >= 0)){
agent.innerText = "현재 맥을 사용하고 화면 크기는 " + screen.width + " *" + screen.height + "입니다.";
document.querySelector("body").classList.add("mac");
} else if (os.indexOf("iphone" >= 0)){
agent.innerText = "현재 아이폰을 사용하고 화면 크기는 " + screen.width + " *" + screen.height + "입니다.";
document.querySelector("body").classList.add("iphon");
} else if (os.indexOf("android" >= 0)){
agent.innerText = "현재 안드로이드를 사용하고 화면 크기는 " + screen.width + " *" + screen.height + "입니다.";
document.querySelector("body").classList.add("android");
}
}
window.onload = function(){
printTime();
printAgent();
}
</script>
음악 플레이어
음악 이전 다음버튼은 슬라이드 이펙트에서 만든것처럼 삼항연산자로 식을 만들어줍니다. 음악 진행시간은 timeupdate을 사용해서 음악이 현재 진행되고있는 값을 불러와서 그 값만큼 width값을 넣어줍니다. 그래서 노래가 진행되는 만큼 width값으로 환산해서 실시간으로 게이지가 차는것처럼 만들어줍니다. 나머지 궁금하신 부분은 주석쪽을 확인해주시기 바랍니다.
<script>
const allMusic = [
{
name : "1. Cottonmouth -",
artist : "Whole Other",
img: "img01",
audio: "music_audio01"
},
{
name : "2. Down With Your Getup -",
artist : "Mini Vandals",
img: "img02",
audio: "music_audio02"
},
{
name : "3. Hey There -",
artist : "half.cool",
img: "img03",
audio: "music_audio03"
},
{
name : "4. Keep On Movin' -",
artist : "King Canyon",
img: "img04",
audio: "music_audio04"
},
{
name : "5. Kind of a Party -",
artist : "Mini Vandals",
img: "img05",
audio: "music_audio05"
},
{
name : "6. Love the Messenger -",
artist : "Freedom Trail Studio",
img: "img06",
audio: "music_audio06"
},
{
name : "7. No Doubt -",
artist : "Yung Logos",
img: "img07",
audio: "music_audio07"
},
{
name : "8. South Street Strut -",
artist : "The Great North Sound Society",
img: "img08",
audio: "music_audio08"
},
{
name : "9. The Monuments and Tunnels -",
artist : "Bail Bonds",
img: "img09",
audio: "music_audio09"
},
{
name : "10. Yes and No at the Same Time -",
artist : "half.cool",
img: "img10",
audio: "music_audio10"
}
]
const musicWrap = document.querySelector(".music__wrap");
const musicView = musicWrap.querySelector(".music__view .img img");
const musicName = musicWrap.querySelector(".music__view .title h3");
const musicArtist = musicWrap.querySelector(".music__view .title p");
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(".music__control .progress .bar");
const musicProgressCurrent = musicWrap.querySelector(".music__control .timer .current");
const musicProgressDuration = musicWrap.querySelector(".music__control .timer .duration");
const musicRepeat = musicWrap.querySelector("#control-repeat");
const musicListBtn = musicWrap.querySelector("#control-list");
const musicList = musicWrap.querySelector(".music__list");
const musicListUl = musicWrap.querySelector(".music__list ul");
const closeBtn = musicWrap.querySelector(".music__list .close_btn");
let musicIndex = 1; // 현재 음악 인덱스
// 음악 재생
function loadMusic(num){
musicName.innerText = allMusic[num-1].name; // 뮤직 이름 로드
musicArtist.innerText = allMusic[num-1].artist; // 뮤직 아티스트 로드
musicView.src = `../assets/img/${allMusic[num-1].img}.png`; // 뮤직 이미지 로드
musicView.alt = allMusic[num-1].name; // 뮤직 이미지 alt태그 로드
musicAudio.src = `../assets/audio/${allMusic[num-1].audio}.mp3` // 뮤직 로드
}
// 재생 버튼
function playMusic(){
musicWrap.classList.add("paused");
musicPlay.setAttribute('title', '정지');
musicPlay.setAttribute('class', 'stop');
musicAudio.play();
};
// 정지 버튼
function pauseMusic(){
musicWrap.classList.remove("paused");
musicPlay.setAttribute('title', '재생');
musicPlay.setAttribute('class', 'play');
musicAudio.pause();
};
// 이전곡 듣기
function prevMusic(){
musicIndex == 1 ? musicIndex = allMusic.length : musicIndex--;
loadMusic(musicIndex);
playMusic();
playListMusic();
};
// 다음곡 듣기
function nextMusic(){
musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
loadMusic(musicIndex);
playMusic();
playListMusic();
};
// 뮤직 진행바
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}`; //초가 한자릿수일때 앞에 0을 붙임
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; // 백분위로 나눈 숫자에 다시 전체 길이를 곱해서 현재 재생값으로 바꿈
});
// 반복 버튼 클릭
musicRepeat.addEventListener("click",()=>{
let getAttr = musicRepeat.getAttribute("class");
switch(getAttr){
case "repeat" :
musicRepeat.setAttribute("class", "repeat-one");
musicRepeat.setAttribute("title", "한곡 반복");
break;
case "repeat-one":
musicRepeat.setAttribute("class", "shuffle");
musicRepeat.setAttribute("title", "랜덤 반복");
break;
case "shuffle":
musicRepeat.setAttribute("class", "repeat");
musicRepeat.setAttribute("title", "전체 반복");
break;
}
})
// 오디오 끝나면
musicAudio.addEventListener("ended", ()=> {
let getAttr = musicRepeat.getAttribute("class");
switch(getAttr){
case "repeat" :
nextMusic();
break;
case "repeat-one" :
playMusic();
break;
case "shuffle" :
let randomIndex = Math.floor(Math.random() * allMusic.length + 1 ); //랜덤 인덱스 생성
do {
randomIndex = Math.floor(Math.random() * allMusic.length + 1 );
} while ( musicIndex == randomIndex )
musicIndex = randomIndex; // 현재 인덱스를 랜덤 인덱스 변경
loadMusic(musicIndex); // 랜덤 인덱스가 반영된 현재 인덱스 값으로 음악을 다시 로드
playMusic(); // 로드한 음악을 재생
break;
}
playListMusic(); //재생목록 업데이트
})
// 플레이 버튼
musicPlay.addEventListener("click", ()=>{
const isMusicPaused = musicWrap.classList.contains("paused"); //음악이 재생중
isMusicPaused ? pauseMusic() : playMusic();
})
// 정지 버튼
musicPlay.addEventListener("click", ()=>{
})
// 다음곡 버튼
musicNextBtn.addEventListener("click", ()=>{
nextMusic();
})
// 이전곡 버튼
musicPrevBtn.addEventListener("click", ()=>{
prevMusic();
})
// 뮤직 리스트 버튼
musicListBtn.addEventListener("click", ()=>{
musicList.classList.toggle("show");
})
closeBtn.addEventListener("click", ()=>{
musicList.classList.remove("show");
})
// 뮤직 리스트 구현하기
for(let i = 0; i < allMusic.length; i++){
let li = `
<li data-index="${i+1}">
<strong>${allMusic[i].name}</strong>
<em>${allMusic[i].artist}</em>
<audio class="${allMusic[i].audio}" src ="../assets/audio/${allMusic[i].audio}.mp3"></audio>
<span class="audio-duration" id="${allMusic[i].audio}">재생시간</span>
</li>
`;
// musicListUl.innerHTML += li; // 한번에 로딩되어서 인식이 잘 안됌
musicListUl.insertAdjacentHTML("beforeend", li); // 하나씩 넣어져서 인식
// 리스트에 음악 시간 불러오기
let liAudioDuration = musicListUl.querySelector(`#${allMusic[i].audio}`); // li 리스트에서 시간을 표시할 선택자를 가져옴
let liAudio = musicListUl.querySelector(`.${allMusic[i].audio}`); // li 리스트에서 오디오를 가져옴
liAudio.addEventListener("loadeddata", ()=>{
let audioDuration = liAudio.duration; // 오디오 전체 길이
let totalMin = Math.floor(audioDuration / 60); // 전체 길이를 분 단위로 쪼갬
let totalSec = Math.floor(audioDuration % 60); // 초 계산
if(totalSec < 10) totalSec = `0${totalSec}`; // 일 자리에 0 추가
liAudioDuration.innerText = `${totalMin}:${totalSec}`; //문자열 출력
liAudioDuration.setAttribute("data-duration", `${totalMin}:${totalSec}`);
});
}
// 뮤직 리스트를 클릭하면 재생
function playListMusic(){
const musicListAll = musicListUl.querySelectorAll("li"); // 뮤직 리스트 목록
for(let i=0; i<musicListAll.length; i++){
let audioTag = musicListAll[i].querySelector(".audio-duration");
if(musicListAll[i].classList.contains("playing")){ // 플레잉 클래스 존재 여부 확인
musicListAll[i].classList.remove("playing"); // 플레잉 클래스 제거
let adDuration = audioTag.getAttribute("data-duration"); //데이터 듀레이션 값 가져오기
audioTag.innerText = adDuration; // 오디오 태그에 데이터 듀레이션값 출력
}
if(musicListAll[i].getAttribute("data-index") == musicIndex){ //현재 실행중인 데이터 인덱스값과 뮤직 인덱스값이 같을 경우
musicListAll[i].classList.add("playing"); // 플레잉 클래스 추가
audioTag.innerText = "재생중" // 재생중일 경우 텍스트 '재생중' 출력
}
musicListAll[i].setAttribute("onclick", "clicked(this)");
}
}
// 뮤직 리스트 클릭하면...
function clicked(el){
let getliIndex = el.getAttribute("data-index"); // 클릭한 리스트의 인덱스값 저장
musicIndex = getliIndex; // 클릭한 인덱스 값을 뮤직 인덱스에 저장
loadMusic(musicIndex); // 해당 인덱스 뮤직 로드
playMusic(); // 음악 재생
playListMusic(); // 음악 리스트 업데이트
}
window.addEventListener("load", ()=> {
loadMusic(musicIndex); // 음악 재생
playListMusic(); // 리스트 초기화
})
// 볼륨 조절
const audio = document.getElementById("main-audio");
const audioVolume = document.getElementById("volume-control");
const volumeIcon = document.querySelector(".volume_icon");
const volumeOffIcon = document.querySelector(".volumeOff_icon");
audioVolume.addEventListener("change", function (e) {
audio.volume = this.value / 10;
if (this.value == 0) {
volumeIcon.classList.add("hide");
volumeOffIcon.classList.add("show");
} else {
volumeIcon.classList.remove("hide");
volumeOffIcon.classList.remove("show");
}
});
</script>
'Javascript_Effect' 카테고리의 다른 글
슬라이드 이펙트 - 이미지 슬라이드(버튼, 닷메뉴, 무한) (1) | 2022.10.20 |
---|---|
게임 이펙트 - 스피드 퀴즈 (1) | 2022.10.17 |
서치 이펙트 - 정렬하기 (0) | 2022.10.17 |
슬라이더 이펙트 - (버튼, 닷메뉴) (3) | 2022.10.14 |
패럴랙스 이펙트 - 리빌 효과 (4) | 2022.10.06 |
댓글