티스토리 뷰

 

뮤직 플레이어가 나오는 사이트를 제작해봤습니다!

처음에 사이트에 들어올때 등록되어있는 노래중 랜덤으로 한곡 시작하게되고 한곡 반복듣기, 랜덤 듣기, 리스트 순서대로 듣기를 구현 하였고 리스트를 누르면 노래 리스트가 나오며 노래 리스트에서 노래를 선택하면 선택한 노래가 틀어지도록 구현하였습니다. 맨아래 참조사이트가 있습니다. 모든소스를 볼수있으니 참조사이트에서 확인하셔도 됩니다!

 

 

HTML 과 CSS 소스입니다.

 <head>
       <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Poppins";
        }
        :root {
            --pink : #FF74A4;
            --violet : #9F6EA3;
            --white : #fff;
            --lightshadow : rgba(0, 0, 0, 0.15);
            --lightblack : #515C6F;
            --pinkshadow : #FFCBDD;
            --darkwhite : #CECACA;
        }
        body {
            height: 100vh;
            background: linear-gradient(var(--pink) 0%, var(--violet) 100%);
        }
        .wrap__music {
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 100%;
            user-select: none;
        }
        .music__inner {
            width: 380px;
            padding: 25px 30px;
            overflow: hidden;
            position: relative;
            border-radius: 15px;
            background: var(--white);
            box-shadow: 0px 6px 15px var(--lightshadow);
        }
        .music__top {
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .music__top i {
            font-size: 30px;
            color: var(--lightblack);
        }
        .music__top h3 {
            font-size: 18px;
            color: var(--lightblack);
            font-weight: 500;
        }
        .music__img {
            width: 100%;
            height: 256px;
            overflow: hidden;
            border-radius: 15px;
            margin-top: 25px;
            box-shadow: 0px 6px 12px var(--lightshadow);
        }
        .music__img img {
            width: 100%;
            height: 100%;
            vertical-align: top;
            object-fit: cover;
        }
        .music__song {
            text-align: center;
            margin: 30px;
        }
        .music__song p {
            color: var(--lightblack);
        }
        .music__song .name {
            font-size: 21px;
        }
        .music__song .artist {
            font-size: 18px;
            opacity: 0.9;
            line-height: 35px;
            font-weight: 300;
        }
        .music__progress {
            height: 6px;
            width: 100%;
            border-radius: 10px;
            background: #F0F0F0;
            cursor: pointer;
        }
        .music__progress .bar {
            height: inherit;
            width: 0%;
            position: relative;
            border-radius: inherit;
            background: linear-gradient(90deg, var(--pink) 0%, var(--violet) 100%);
        }
        .music__progress .timer {
            margin-top: 2px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            color: var(--lightblack);
            font-size: 0.9em;
            pointer-events: none;
        }
        .music__control {
            margin-top: 40px;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .music__control i {
            font-size: 28px;
            user-select: none;
            background: linear-gradient(90deg, var(--pink) 0%, var(--violet) 100%);
            background-clip: text;
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .music__control i:nth-child(2),
        .music__control i:nth-child(4) {
            font-size: 40px;
        }
        .music__control .play-pause {
            width: 54px; height: 54px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            background: linear-gradient(var(--white) 0%, var(--darkwhite) 100%);
            box-shadow: 0 0 0 2px var(--pink);
            z-index: 1;
        }
        .music__control .play-pause::before {
            content :'';
            width: 40px; height: 40px;
            border-radius: inherit;
            background: linear-gradient(var(--pink) 0%, var(--violet) 100%);
            position: absolute;
            z-index: -1;
        }
        .music__control .play-pause i {
            -webkit-text-fill-color: var(--white);
            opacity: 0.8;
        }
        .music__list {
            position: absolute;
            background: var(--white);
            width: 100%;
            left: 0;
            z-index: 10;
            border-radius: 15px;
            padding: 15px 30px;
            box-shadow: 0 -3px 10px rgba(0,0,0,0.1);
            transition: all 0.15s ease-out;
            bottom: -400px;
            opacity: 0;
            pointer-events: none;
        }
        .music__list.show {
            bottom: 0;
            opacity: 1;
            pointer-events: auto;
        }
        .music__list .title {
            display: flex;
            align-items: center;
            justify-content: space-between;
            color: var(--lightblack);
            margin-bottom: 10px;
        }
        .music__list .title .queue {
            vertical-align: -6px;
        }
        .music__list .list {
            color: var(--lightblack)
        }
        .music__list .list > ul {
            max-height: 260px;
            margin: 10px 0;
            overflow: auto;
        }
        .music__list .list > ul::-webkit-scrollbar {
            width: 0;
        }
        .music__list .list > ul > li {
            display: flex;
            align-items: center;
            justify-content: space-between;
            border-bottom: 1px solid #E5E5E5;
            padding-bottom: 5px;
            margin-bottom: 5px;
        }
        .music__list .list > ul > li.playing {
            color: var(--pink);
        }
        .music__list .list > ul > li > div em {
            font-style: normal;
        }
        .music__list .list > ul > li > div p {
            opacity: 0.8;
        }
    </style>
</head>
<body>
    <div class="wrap__music">
        <div class="music__inner">
            <div class="music__top">
                <i class="material-icons">expand_more</i>
                <h3>Now Playing</h3>
                <i class="material-icons">more_horiz</i>
            </div>
            <!-- /music__top -->
            <div class="music__img">
                <img src="" alt="">
            </div>
            <!-- /music__img -->
            <div class="music__song">
                <p class="name"></p>
                <p class="artist"></p>
            </div>
            <!-- /music__song -->
            <div class="music__progress">
                <div class="bar">
                    <audio id="main-audio" src=""></audio>
                </div>
                <div class="timer">
                    <span class="current">0:00</span>
                    <span class="duration">0:00</span>
                </div>
            </div>
            <!-- /music__progress -->
            <div class="music__control">
                <i id="control-repeat" class="material-icons" title="전체 반복">repeat</i>
                <i id="control-prev" class="material-icons" title="이전곡 재생">skip_previous</i>
                <div class="play-pause">
                    <i id="control-play" class="material-icons" title="재생">play_arrow</i>
                    <!-- <i class="material-icons">pause</i> -->
                </div>
                <i id="control-next" class="material-icons" title="다음곡 재생">skip_next</i>
                <i id="control-list" class="material-icons" title="플레이 리스트">queue_music</i>
                <!-- <i class="material-icons">repeat_one</i>
                <i class="material-icons">shuffle</i> -->
            </div>
            <!-- /music__control -->
            <div class="music__list">
                <div class="title">
                    <div>
                        <i class="material-icons queue">queue_music</i>
                        <span>Music List</span>
                    </div>
                    <i class="material-icons close">close</i>
                </div>
                <div class="list">
                    <ul>
                        <!-- Javascript -->
                        <!-- <li>
                            <div>
                                <em>Thunder</em>
                                <p>가수 이름</p>
                            </div>
                            <span>3:36</span>
                        </li> -->
                    </ul>
                </div>
            </div>
            <!-- /music__list -->
        </div>
    </div>

Script 입니다.

    <script src="api//music.js"></script>
    <script>
        const musicWrap = document.querySelector(".wrap__music");
        const musicImg = musicWrap.querySelector(".music__img img");
        const musicName = musicWrap.querySelector(".music__song .name");
        const musicArtist = musicWrap.querySelector(".music__song .artist");
        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(".music__progress");
        const musicProgressBar = musicProgress.querySelector(".bar");
        const musicProgressCurrent = musicProgress.querySelector(".current");
        const musicProgressDuration = musicProgress.querySelector(".duration");
        const musicRepeat = musicWrap.querySelector("#control-repeat");
        const musicList = musicWrap.querySelector(".music__list");
        const musicListBtn = musicWrap.querySelector("#control-list");
        const musicListClose = musicList.querySelector(".close");
        const musicListUl = musicList.querySelector(".list ul");
     

        let musicIndex = Math.floor((Math.random() * allMusic.length) + 1);

        function loadMusic(num){
            musicImg.src = `images/${allMusic[num-1].img}.png`;
            musicImg.alt = `${allMusic[num-1].img}`;
            musicName.innerText = allMusic[num-1].name;
            musicArtist.innerText = allMusic[num-1].artist;
            musicAudio.src = `songs/${allMusic[num-1].audio}.mp3`;           
        }

        //플레이 버튼
        function playMusic(){
            musicWrap.classList.add("paused");
            musicPlay.innerText = "pause";
            musicPlay.setAttribute("title", "정지")
            musicAudio.play();
        };

        //정지 버튼
        function pauseMusic(){
            musicWrap.classList.remove("paused");
            musicPlay.innerText = "play_arrow";
            musicPlay.setAttribute("title", "재생")
            musicAudio.pause();
        };

        //이전 곡 듣기 버튼 (1)
        function prevMusic(){
            musicIndex--;
            musicIndex < 1 ? musicIndex = allMusic.length : musicIndex = musicIndex;
            loadMusic(musicIndex);
            playMusic();
            playListMusic();
        };

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

        //뮤직 진행바
        musicAudio.addEventListener("timeupdate", (e) => {
            // console.log(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}`;
                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}`;
        });

        //플레이 버튼
        musicPlay.addEventListener("click", () => {
            const isMusicPaused = musicWrap.classList.contains("paused");
            isMusicPaused ? pauseMusic() : playMusic();
        });

        //이전곡 버튼 
        musicPrevBtn.addEventListener("click", () => {
            prevMusic();
        });
        //다음곡 버튼
        musicNextBtn.addEventListener("click", () => {
            nextMusic();
        });

        //진행 버튼 클릭
        musicProgress.addEventListener("click", (e) => {
            let progressWidth = musicProgress.clientWidth;
            let clickedOffsetX = e.offsetX;
            let songDuration = musicAudio.duration;

            musicAudio.currentTime = (clickedOffsetX / progressWidth) * songDuration;
            //playMusic(); <<클릭시 바로 진행하려면 주석풀기
        });

        //반복버튼
        musicRepeat.addEventListener("click", () => {
           let getText =  musicRepeat.innerText;
           
           switch(getText){
                case "repeat":
                    musicRepeat.innerText = "repeat_one";
                    musicRepeat.setAttribute("title", "한곡 반복");
                break;
                case "repeat_one":
                    musicRepeat.innerText = "shuffle";
                    musicRepeat.setAttribute("title", "랜덤 반복");
                break;
                case "shuffle":
                    musicRepeat.innerText = "repeat";
                    musicRepeat.setAttribute("title", "전체 반복");
                break;
           }
        });

        //오디오가 끝나고
        musicAudio.addEventListener("ended", () => {
            let getText = musicRepeat.innerText;

            switch(getText){
                case "repeat":
                    nextMusic();
                break;
                case "repeat_one":
                    loadMusic(musicIndex);
                    playMusic();
                break;
                case "shuffle":
                    let randIndex = Math.floor((Math.random() * allMusic.length) + 1);
                    do {
                        randIndex = Math.floor((Math.random() * allMusic.length) + 1);
                    } while (musicIndex == randIndex);
                    musicIndex = randIndex;
                    loadMusic(musicIndex);
                    playMusic();
                    playListMusic();
                break;
            }
        });

        //뮤직 리스트 버튼
        musicListBtn.addEventListener("click", () => {
            musicList.classList.add("show");
        });

        //뮤직 리스트 닫기 버튼
        musicListClose.addEventListener("click", () => {
            musicList.classList.remove("show");
        })

        //뮤직 리스트 구현하기 
        for(let i=0; i<allMusic.length; i++){
            let li =` 
                        <li data-index="${i + 1}">
                            <div>
                                <em>${allMusic[i].name}</em>
                                <p>${allMusic[i].artist}</p>
                            </div>
                            <audio class="${allMusic[i].audio}" src="songs/${allMusic[i].audio}.mp3"></audio>
                            <span id="${allMusic[i].audio}" class="audio-duration">3:36</span>
                        </li>
                    `;
            musicListUl.insertAdjacentHTML("beforeend", li);

            let liAudiolDuration = musicListUl.querySelector(`#${allMusic[i].audio}`);
            let liAudio = musicListUl.querySelector(`.${allMusic[i].audio}`);

            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}`;
                liAudiolDuration.innerText = `${totalMin}:${totalSec}`;
                liAudiolDuration.setAttribute("data-duration", `${totalMin}:${totalSec}`)
            });
        }

        //뮤직 리스트 클릭하기
        function playListMusic(){
            const musicListAll = musicListUl.querySelectorAll("li");
            for(let j=0; j<musicListAll.length; j++){
                let audioTag = musicListAll[j].querySelector(".audio-duration");

                if(musicListAll[j].classList.contains("playing")){
                    musicListAll[j].classList.remove("playing");
                    let adDuration = audioTag.getAttribute("data-duration");
                    audioTag.innerText = adDuration;
                }

                if(musicListAll[j].getAttribute("data-index") == musicIndex){
                    musicListAll[j].classList.add("playing");
                    audioTag.innerText = "Playing";
                }

                musicListAll[j].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();
        });
    </script>

 

참조사이트

 

반응형

'Script Sample > Script Example' 카테고리의 다른 글

타자 연습하기 Typing game  (2) 2022.04.12
댓글
© 2022 babydevelop