[JavaScript] 미니게임 프로젝트 | 메인 페이지

승연·2022년 7월 14일
7

Game World

목록 보기
1/6
post-thumbnail

Game World


💻 프로젝트 의도가 뭔가요?

이제 막 HTML, CSS, JavaScript 기초를 뗀 입문자로서..😅
HTML, CSS, JavaScript와 좀 더 친해지기 위해 미니게임 제작 프로젝트를 시작하게 됐습니다.

(프로젝트 아이디어 및 진행 순서는 teo님의 글을 참고했습니다. 감사합니다.)

🔎 사용 기술은 무엇인가요?

HTML, CSS, JavaScript

🙊 데모 페이지

https://sypear.github.io/game-world/



Game World - 메인 페이지


1. 인트로 화면

까만 배경이 사용하고 있는 기기의 화면에 꽉 차게,
Hello, Game World! 라는 문구가 타이핑하듯 한 글자씩 나오도록 구현하고 싶었습니다.

Hello, World! 가 떠오르도록 지은 문구인데 의도가 전달됐으려나요..🤭

1-1. 화면에 꽉 차게 만들기

1) 반응형 메타 태그 추가

HTML 코드 내에 반응형 메타 태그를 추가했습니다.

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">

2) 이제 화면에 꽉 차게 해보자!

.intro {
    width: 100vw;
    height: 100vh;
}

CSS로 width: 100vw, height: 100vh 값을 주어 화면에 꽉 차게 만들었...는데요.


3) 누구세요..? 😶

갑분 가로 스크롤을 만났습니다.

vw는 화면 오른쪽에 생기는 세로 스크롤바까지 포함하기 때문에 가로 스크롤이 생긴 것이었습니다.

검색 결과, 가로 스크롤이 생기지 않게 하는 방법을 두 개 찾았습니다.

  1. width: 100%를 사용하는 방법
  2. 최상위 태그에 overflow-x: hidden 속성을 주는 방법

이미 width: 100vw 속성을 이용해서 구현하고 있었기 때문에 width: 100%로 변경하고 싶진 않았습니다. (왠지 100vw에게 지는 느낌..)

그래서, Stack Overflow 글을 참고하여 html, body 태그에 overflow-x: hidden 속성을 주어 해결하였습니다.

4) 그런데... 새로고침 할 때마다 스크롤이 내려가요 🤮

위 이미지처럼 새로고침 할 때마다 스크롤이 내려가는 현상이 나타났습니다.

해결 방법을 찾아보니
아래처럼 특정 시간 후에 강제로 스크롤을 최상단으로 올려버리는 방법이 있었지만,

window.onload = function() {
	setTimeout (function () {
		scrollTo(0, 0);
	}, 10);
}

특정 시간 후에 강제로 올리는 방법이 마음에 들지 않아서 검색을 좀 더 해보다가

History 객체의 scrollRestoration 이란 속성을 이용해 스크롤 위치를 제어하는 방법이 있다는 것을 알게 되었습니다. (참고한 페이지)

스크롤을 이전 위치로 복원하지 않도록 하는 (즉, 스크롤을 항상 최상단으로 위치하게 하는) 코드를 추가하여 새로고침 시 자동 스크롤 되는 문제를 해결하였습니다.

if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual'; // 스크롤을 복원하지 않음.
}

1-2. 타이핑 효과

1) JavaScript를 이용한 타이핑 효과

HTML

<header class="intro">
	<h1 class="intro__title" lang="en"
		aria-label="게임 월드에 오신 걸 환영합니다."></h1>
	...
</header>

JavaScript

const introTitle = document.getElementsByClassName("intro__title")[0];

// 타이틀 문구 타이핑
const title = "Hello,\nGame\nWorld!";

let cnt = 0;
let timer = 0;

function typingIntroTitle() {
    let character = title[cnt++];

    if (character === "\n") {
        introTitle.innerHTML = introTitle.innerHTML + "<br/>";
    } else {
        introTitle.innerHTML = introTitle.innerHTML + character;
    }

    if (cnt === title.length) {
        clearInterval(timer);
        
        return;
    }
}

window.onload = function() {
    timer = setInterval(typingIntroTitle, 200);
}

👩‍💻 코드 설명

  1. 타이머 생성
    • 0.2초 간격으로 typingIntroTitle 함수를 호출하는 타이머 생성
timer = setInterval(typingIntroTitle, 200);
  1. 출력하고자 하는 문구를 변수에 저장
const title = "Hello,\nGame\nWorld!";
  1. 카운트를 저장하는 변수 생성 후 한 글자씩 읽도록 하기
let cnt = 0;
let character = title[cnt++];
  1. 한 글자씩 읽어가면서 HTML에도 한 글자씩 추가
    • 이때, \n를 만나면 <br/>로 대체하도록 함
if (character === "\n") {
	introTitle.innerHTML = introTitle.innerHTML + "<br/>";
} else {
	introTitle.innerHTML = introTitle.innerHTML + character;
}
  1. 문구를 다 읽으면 타이머 종료
if (cnt === title.length) {
	clearInterval(timer);

	return;
}

2) 깜빡이는 커서는?

CSS

.intro__title:after {
    content: '|';
    display: inline-block;
    font-size: 70px;
    animation: moveCursor 500ms infinite;
}

@keyframes moveCursor {
    from {
        opacity: 1;
    }
    
    to {
        opacity: 0;
    }
}

👩‍💻 코드 설명

커서 콘텐츠(|)의 경우 의미 있는 정보가 아니기 때문에 HTML 문서에 포함하지 않고 CSS 가상 요소를 사용하여 만들었습니다.

깜빡이는 효과는 animation을 이용하여 구현했습니다.




2. 게임 메뉴로 스르륵 이동하는 효과

타이틀 문구 타이핑이 끝난 후 게임 메뉴로 이동하는 버튼이 나타나도록 했습니다.
그리고 그 버튼을 클릭하면 게임 메뉴로 스르륵.. 이동하는 효과를 넣었습니다.

스르륵.. 효과는 JavaScript의 scrollIntoView() 메소드를 이용하여 구현했습니다. (참고한 페이지)

JavaScript

const introButton = document.getElementsByClassName("intro__button")[0];
const game = document.getElementById("game");

// 버튼 클릭 시 게임 목록으로 이동
introButton.addEventListener('click', () => {
    game.scrollIntoView({behavior: "smooth"});
});



3. 게임 메뉴

커서가 올라갔을 때 메뉴가 튀어나오는 듯한 효과를 주고 싶었습니다.
그리고 각 게임 메뉴를 클릭하면 해당 게임 페이지로 이동할 수 있도록 구현하고 싶었습니다.


3-1. 커서가 올라갔을 때 효과

CSS

.game__wrapper {
	position: relative;
    bottom: 0;
	...
    box-shadow: rgba(50, 50, 105, 0.15) 0px 2px 5px 0px, rgba(0, 0, 0, 0.05) 0px 1px 1px 0px;
    transition: bottom 250ms ease-in,
                box-shadow 250ms ease-in;
}

.game__wrapper:hover {
    bottom: 5px;
    box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
}

👩‍💻 코드 설명

CSS의 :hover를 이용하여 커서가 올라갔을 때
bottom은 5px만큼 이동하고, box-shadow는 좀 더 진해지도록 했습니다.
(box-shadow는 Beautiful CSS box-shadow examples 페이지를 참고했습니다.)

그리고 샤라락.. 스러운 효과를 위해서 transition을 이용하였습니다.


3-2. 링크는 어떻게 걸지?

각 게임 메뉴 영역 어디든 클릭하면 해당 게임 페이지로 이동할 수 있도록 구현하고 싶었습니다.

HTML

<main id="game" aria-label="게임 목록">
	<article class="game__wrapper" id="rock-paper-scissors"> <!-- 게임 메뉴 영역 -->
		<a class="game__overlay" href="./game-rps.html"
           aria-label="가위 바위 보 게임: 컴퓨터와 가위 바위 보 대결을 해보세요."> <!-- a 태그 영역 -->
		</a>
		...
	</article>
</main>

CSS

.game__wrapper { /* 게임 메뉴 영역(부모 요소) */
    position: relative;
    ...
}

.game__overlay { /* a 태그 영역 */
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 2;
}

👩‍💻 코드 설명

그래서 HTML 구성을 어떻게 할지 고민하다가

a 태그의 크기를 부모 요소의 크기와 같게 한 후 z-index를 큰 값으로 설정하여 위에서 덮어버리도록 구현했습니다.




미니 프로젝트 끝까지 한 번 가보자고~~~

profile
✈️ https://sypear.tistory.com/

2개의 댓글

comment-user-thumbnail
2022년 8월 12일

화이팅하세요!

1개의 답글