JAVASCRIPT

게임이펙트01 - 버튼클릭 동작

ture403 2023. 4. 27. 19:39

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

완성된 화면 입니다.

 

HTML 화면입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GAME Effect</title>
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/bg.css">
    <link rel="stylesheet" href="css/music.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>  
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script defer src="js/music.js"></script>
</head>
<body>
    <div class="cursor">
        <img src="img/game_mouse01.png" alt>
    </div>
    <header id="header">
        <h1>hello Game World</h1>
        <div class="time">2023년 4월 24일 16시 50분</div>
    </header>

    <main>
        <div class="icon_box">
            <div class="icon1">
                <img src="img/game_icon01.png" alt="뮤직">
                <span>뮤직 듣기</span>
            </div>
            <div class="icon2">
                <img src="img/game_icon02.png" alt="뮤직">
                <span>아이 듣기</span>
            </div>
            <div class="icon3">
                <img src="img/game_icon03.png" alt="뮤직">
                <span>소리 듣기</span>
            </div>
            <div class="icon4">
                <img src="img/game_icon04.png" alt="뮤직">
                <span>사운 듣기</span>
            </div>
        </div>

        <!-- 뮤직 플레이어 -->
        <div class="music_wrap">
            <div class="music_inner">
                <div class="music_header">
                    <span class="left"></span>
                    <h2>music player</h2>
                    <span class="right"></span>
                </div>
                <div class="music_contents">
                    <div class="music_view">
                        <div class="images">
                            <img src="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="current">0:00</span>
                                <span class="duration">3:55</span>
                            </div>
                        </div>
                        <div class="control">
                            <span>
                                <i class="repeat" id="control-repreat" 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>
        <!-- 뮤직 플레이어 -->
    </main>

    <footer id="footer">
        <div class="info">현재 맥을 사용하고 있으면, 화면크기는 1920 X 760 입니다.</div>
    </footer>
    <script>
        const Header = document.querySelector("#header");
        const Time1 = document.querySelector(".time");
        const info = document.querySelector(".info");
        const iconBox = document.querySelectorAll(".icon_box  div");
        const icon1 = document.querySelector(".icon1");
        
        $(".icon1").draggable({ 
            containment: ".icon_box", 
            scroll: false ,
            start: function() {
                $(".cursor img").attr("src", "img/game_mouse01.png")
                $(".info").html("뮤직듣기가 드래그가 실행 되었습니다.");
                $("#header").css("background-color", "#EC3A8B");
            },
            drag :function() {
                $(".info").html("뮤직듣기가 드래그가 실행 중입니다..");
            },
            stop : function() {
                $(".info").html("뮤직듣기가 드래그가 중지되었습니다..");
                $("#header").css("background-color", "#000");
                setTimeout(()=>{
                    const width = window.screen.width;
                    const height = window.screen.height;
                    const os = navigator.userAgent.toLocaleLowerCase();
                    if (os.includes('win')) {
                        $(".info").html(`현재 window을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('mac')) {
                        $(".info").html(`현재 mac을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('android')) {
                        $(".info").html(`현재 android을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else {
                        $(".info").html(`현재 unknown을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    }
                },10000);
            }
        });
        $(".icon2").draggable({ 
            containment: ".icon_box", 
            scroll: false,  
            start: function() {
                $(".cursor img").attr("src", "img/game_mouse02.png")
                $(".info").html("뮤직듣기가 드래그가 실행 되었습니다.");
                $("#header").css("background-color", "#3B5EC3")
            },
            drag :function() {
                $(".info").html("뮤직듣기가 드래그가 실행 중입니다..");
            },
            stop : function() {
                $(".info").html("뮤직듣기가 드래그가 중지되었습니다..");
                $("#header").css("background-color", "#000");
                setTimeout(()=>{
                    const width = window.screen.width;
                    const height = window.screen.height;
                    const os = navigator.userAgent.toLocaleLowerCase();
                    if (os.includes('win')) {
                        $(".info").html(`현재 window을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('mac')) {
                        $(".info").html(`현재 mac을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('android')) {
                        $(".info").html(`현재 android을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else {
                        $(".info").html(`현재 unknown을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    }
                },10000);
            }
        });
        $(".icon3").draggable({ 
            containment: ".icon_box", 
            scroll: false,  
            start: function() {
                $(".cursor img").attr("src", "img/game_mouse03.png")
                $(".info").html("뮤직듣기가 드래그가 실행 되었습니다.");
                $("#header").css("background-color", "#7FFF5B")
            },
            drag :function() {
                $(".info").html("뮤직듣기가 드래그가 실행 중입니다..");
            },
            stop : function() {
                $(".info").html("뮤직듣기가 드래그가 중지되었습니다..");
                $("#header").css("background-color", "#000");
                setTimeout(()=>{
                    const width = window.screen.width;
                    const height = window.screen.height;
                    const os = navigator.userAgent.toLocaleLowerCase();
                    if (os.includes('win')) {
                        $(".info").html(`현재 window을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('mac')) {
                        $(".info").html(`현재 mac을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('android')) {
                        $(".info").html(`현재 android을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else {
                        $(".info").html(`현재 unknown을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    }
                },10000);
            },
        });
        $(".icon4").draggable({ 
            containment: ".icon_box", 
            scroll: false, 
            start: function() {
                $(".cursor img").attr("src", "img/game_mouse04.png")
                $(".info").html("뮤직듣기가 드래그가 실행 되었습니다.");
                $("#header").css("background-color", "#FFFF50")
            },
            drag :function() {
                $(".info").html("뮤직듣기가 드래그가 실행 중입니다..");
            },
            stop : function() {
                $(".info").html("뮤직듣기가 드래그가 중지되었습니다..");
                $("#header").css("background-color", "#000");
                setTimeout(()=>{
                    const width = window.screen.width;
                    const height = window.screen.height;
                    const os = navigator.userAgent.toLocaleLowerCase();
                    if (os.includes('win')) {
                        $(".info").html(`현재 window을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('mac')) {
                        $(".info").html(`현재 mac을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else if (os.includes('android')) {
                        $(".info").html(`현재 android을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    } else {
                        $(".info").html(`현재 unknown을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
                    }
                },10000);
            },
        });
        
        window.onload = function(){
            window.addEventListener("mousemove", e=>{
            gsap.to(".cursor", {
                duration: 0, 
                left : e.pageX -5,
                top: e.pageY -5
                })
            });
            setInterval(printTime,1000)
            printAgent(); // 하단 중앙
        }
        
        function printTime(){
            let now = new Date();
            let year = now.getFullYear().toString();
            let month = (now.getMonth() + 1).toString().padStart(2, '0');
            let date = now.getDate().toString().padStart(2, '0'); 
            let hours = now.getHours().toString().padStart(2, '0');
            let minutes = now.getMinutes().toString().padStart(2, '0');
            let seconds = now.getSeconds().toString().padStart(2, '0');
            Time1.innerHTML = `${year}년 ${month}월 ${date}일 ${hours}시 ${minutes}분 ${seconds}초`;
        }

        function printAgent() {
            const width = window.screen.width;
            const height = window.screen.height;
            const os = navigator.userAgent.toLocaleLowerCase();
            if (os.includes('win')) {
                $(".info").html(`현재 window을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
            } else if (os.includes('mac')) {
                $(".info").html(`현재 mac을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
            } else if (os.includes('android')) {
                $(".info").html(`현재 android을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
            } else {
                $(".info").html(`현재 unknown을 사용하고 있으면, 화면크기는 ${width} X ${height} 입니다.`);
            }
        }
        


        iconBox.forEach((icon, index) => {
            icon.addEventListener("click", () => {
                const colors = ["#EC3A8B", "#3B5EC3", "#7FFF5B", "#FFFF50"];
                Header.style.backgroundColor = colors[index];
                if (index === 3) {
                    Header.style.color = "#FFFF50";
                } else {
                    Header.style.color = "";
                }
            });
        });
        
    </script>
</body>
</html>

css 코드입니다.

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100&display=swap');

.music_inner {
    width: 350px;
    /* background: rgba(0,0,0,0.5); */
    filter: blur(0.3);
    backdrop-filter: blur(20px);
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    padding: 20px 22px;
    border-radius: 20px;
    box-shadow: 0 60px 100px rgba(0,0,0,0.4);
}
.music_header {
}
.music_header h2 {
    text-align: center;
    font-size: 14px;
    padding-top: 3px;
    font-family: 'Poppins' !important;
    font-weight: 200;
}
.music_header .left {}
.music_header .right {}
.music_contents {}
.music_view {
    position: absolute;
    left: 50%;
    transform: translate(-50%);
    top: 50px;
    padding: 0 20px 20px 20px;
    width: 90%;
}
.music_view .image {
}
.music_view .image img {
    border-radius: 20px;
    box-shadow: 0 20px 50px rgba(246, 50, 50, 0.4);
}
.music_control {
    background-color: #fff;
    height: 400px;
    border-radius: 15px;
    margin-top: 200px;
    padding: 20px;
}
.music_control .title {
    text-align: center;
    padding-top: 120px;
}
.music_control .title h3 {
    margin-bottom: 5px;
    color: #000;
    font-size: 20px;
}
.music_control .title p {
    color: #666;
    font-size: 16px;
    margin-bottom: 20px;
}
.music_control .progress {
    background-color: #ccc;
    height: 5px;
    border-radius: 3px;
}
.music_control .progress .bar {
    width: 0%;
    background-color: #1d94b8;
    height: 5px;
    border-radius: 3px;
}
.music_control .progress .timer {
    display: flex;
    justify-content: space-between;
    margin-top: 3px;
}
.music_control .progress .timer span {
    color: #000;
    font-size: 12px;
}
.music_control .control {
    width: 100%;
    height: 100px;
    margin-top: 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.music_control .control span {
    display: inline-block;
    width: 40px;
    height: 40px;
}
.music_control .control span:active {
    background-color: #eaeaea;
    border-radius: 50%;
}
.music_control .control span i {
    width: 40px;
    height: 40px;
    display: block;
    background-image: url(../img/music_icon.svg);
    background-color: 500px;
}
.music_control .control span i.repeat {
    background-position: 0 0;
}
.music_control .control span i.prev {
    background-position: -120px 0;
}
.music_control .control span i.play {
    background-position: -160px 0;
}
.music_control .control span:nth-child(3) {
    background:linear-gradient(90deg,#2387a5,#a841a5) ;
    border-radius: 50%;
}
.music_control .control span i.next {
    background-position: -240px 0;
}
.music_control .control span i.list {
    background-position: -280px 0;
}
.music_control .control span i.repeat_one {
    background-position: -40px 0;
}
.music_control .control span i.shuffle {
    background-position: -80px 0;
}
.music_control .control span i.stop {
    background-position: -200px 0;
}
.music_footer {}

 

JS코드입니다.

//전체 이미지와 오디오 객체에 저장
const allMusic = [
    {
        name : "1. 저리가라",
        artist : "partick",
        img : "music_view01",
        audio : "music_audio01"
    },{
        name : "2. 저리가라",
        artist : "partick",
        img : "music_view02",
        audio : "music_audio02"
    },{
        name : "3. 저리가라",
        artist : "partick",
        img : "music_view03",
        audio : "music_audio03"
    },{
        name : "4. 저리가라",
        artist : "partick",
        img : "music_view04",
        audio : "music_audio04"
    },{
        name : "5. 저리가라",
        artist : "partick",
        img : "music_view05",
        audio : "music_audio05"
    },{
        name : "6. 저리가라",
        artist : "partick",
        img : "music_view06",
        audio : "music_audio06"
    },{
        name : "7. 저리가라",
        artist : "partick",
        img : "music_view07",
        audio : "music_audio07"
    },{
        name : "8. 저리가라",
        artist : "partick",
        img : "music_view08",
        audio : "music_audio08"
    },{
        name : "9. 저리가라",
        artist : "partick",
        img : "music_view09",
        audio : "music_audio09"
    },{
        name : "10. 저리가라",
        artist : "partick",
        img : "music_view10",
        audio : "music_audio10"
    },
];

//선언자
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 .images 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 musicProgress = musicWrap.querySelector(".progress");
const musicProgressBar = musicWrap.querySelector(".progress .bar");
const musicProgressCurrent = musicWrap.querySelector(".progress .timer .current");
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 = `img/${allMusic[num-1].img}.png`; //뮤직 이미지
    musicView.alt = allMusic[num-1].name; //뮤직이미지 alt
    musicAudio.src =`audio/${allMusic[num-1].audio}.mp3`; //뮤직이미지 alt
}

//재생버튼
const playMusic = () => {
    musicWrap.classList.add("paused"); //paused를 클래스에 추가
    musicplay.setAttribute("title", "정지"); //musicplay에 title 을 정지로 변경
    musicplay.setAttribute("class", "stop"); //musicplay에 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 = () => {
    // musicIndex++;
    // if(musicIndex > 10)musicIndex = 1;

    musicIndex == allMusic.length ? musicIndex = 1 : musicIndex++;
    loadMusic(musicIndex);
    playMusic();
}

// 뮤직 진행바
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 audiodrutaion = musicAudio.duration;
        let totalMin = Math.floor(audiodrutaion / 60);
        let totalSec = Math.floor(audiodrutaion % 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}`;
})
//진행 버튼 클릭
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);
});

 

자바스크립트 JS만 설명

  • 먼저 변수 allMusic 안에 제이슨형식으로 작성을 했습니다.
  • 그리고 필요한 선언자를 불러왔습니다.
  • 음악재생을 위한 함수를 만들었습니다. 그안에 allMusic안에 있는 데이터를 불러와서 innerText를 통해서 출력했습니다.
  • 재생버튼을 위한 함수를 만들었습니다. 그안에 musciWarp에 클래스를 paused를 붙였습니다. 그후 setAttribute를 이용해서 title과 class를 변경해서 stop를 나오게 표출했습니다. 그다음 play()함수를 써서 노래를 출력하게 했습니다.
  • 정지버튼을 만들었습니다. 그안에 paused를 지우고 그다음 setAttribute를 이용해서 title 과 class 를 변경해서 재생버튼이 나오게 했습니다. pause()를 이용해서 음악을 정지했습니다.
  • 이전곡 듣기 함수를 만들었습니다. 그안에 음악재생 함수를 넣고 재생버튼 함수도 넣었습니다. 음악재생 함수 매개변수에 musicIndex 값을 가져와서 1 보다 작으면 allMusic의 총갯수로 변경해 주는 조건물을 넣어서 매개변수에 넣었습니다.
  • 다음곡듣기 함수를 만들었습니다. 그안에 그안에 이전곡 듣기와 같이 musicIndex 값을 allMusic총갯수 면 다시 1로 변경되게 조건문을 적고 그안에  음악재생 함수랑 재생버튼 함수를 넣었습니다.
  • JavaScript에서 timeupdate 이벤트는 HTML5 <audio> 또는 <video> 요소에서 재생 위치가 변경될 때마다 발생하는 이벤트입니다. 이 이벤트를 통해서 뮤직 진행됬을때 이벤트처리를 할겁니다. 그안에 현재 재생되는 시간, 오디오 총길이를 변수에 담았습니다. (e)를 통해서 그안에 있는 값을 갖고와서 처리했습니다. 그리고 재생바에 값을 넣어주기위해서 전체길이에서 현재진행되는시간을 나누었습니다. 그리고 widh값을 style로 불러와서 그안에 변수를 넣어서 처리했습니다.
  • loadeddata 이벤트는 HTML5 <video> 요소 또는 <audio> 요소가 로드된 미디어 데이터의 일부를 재생할 수 있을 때 발생하는 이벤트입니다. 이걸동해서 진행시간을 가져올겁니다. 거기서 duration을 쓰면 전체 오디오파일의 길이를 알수있습니다. 그러나 초단위이기 때문에 변수에 분 과 초를 담았습니다. 그리고 한자리숫자일때 0을 추가하는 조건식을 추가 했습니다. 그리고 innerText를 통해 출력했습니다.

  • 그다음 진행시간을 표출하는 코드를 설명하겠습니다.  현재 재생되는 시간에 60을 나누면 분 단위 진행시간이 됩니다. 그다음 현재 재생되는 시간에 나 %연산자를 쓰면 진행되는 초가 됩니다. 그다음 조건식에 숫자가 10보다 작으면 0을 붙이는게 했고 그다음 innerText를 통해서 출력했습니다.
  • 진행버튼 클릭시 동작하는 함수를 설명하겠습니다. 먼저 전체 진행하는 길이를 변수에 담고 진행바 기준으로 측정되는 x좌표값을 변수에 넣었습니다 .(e).offsetX를 사용하면 됩니다. 그리고 오디오 전체 길이를 변수에 담아서 x좌표값을 전체 진행길이로 나눈후 전체 길이를 곱해주면 뮤직 진행바를 아무데다 클릭하면 진행이 됩니다.
  • 플레이버튼 클릭시 동작하는 함수를 설명하겠습니다. 먼저  클래스에 paused가 붙은걸 찾아서 삼항연사자를 사용했습니다. 조건식에 맞으면 중지하는함수를 실행하고 아니면 재생하는 함수를 실행하게 해주었습니다.
  • 이전곡,다음곡 버튼 클릭시 함수 이벤트 안에는 이전함수 와 다음함수를 넣어서 동작하게 만들었습니다.

몰랐던 메서드 정리

메서드 내용
loadeddata HTML5 <video> 요소 또는 <audio> 요소가 로드된 미디어 데이터의 일부를 재생할 수 있을 때 발생하는 이벤트
timeupdate 이벤트는 HTML5 <audio> 또는 <video> 요소에서 재생 위치가 변경될 때마다 발생하는 이벤트입니다.

 

이전 소스 보기

https://ture403.tistory.com/87

 

자바스크립트 게임 이펙트 01

완성된 화면 입니다. HTML 화면입니다. hello Game World 2023년 4월 24일 16시 50분 뮤직 듣기 아이 듣기 소리 듣기 사운 듣기 현재 맥을 사용하고 있으면, 화면크기는 1920 X 760 입니다. css 코드입니다. * { c

ture403.tistory.com

전체 코드 보기 

https://github.com/ture403/web2023/tree/main/javascript/game