Vanilla JS를 이용한 서비스
- vanilla js로 배경이미지 랜덤 변경
- vanilla js로 인사 만들기
- vanilla js로 시계 만들기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<main>
<section class="clock">
<h1 class="clock__title"></h1>
</section>
<section class="greeting">
<h2 class="greeting__title">Hello, what's your name?</h2>
<form class="greeting__form">
<input type="text" class="greeting__form__input" />
</form>
</section>
</main>
<footer>
<p class="quote"></p>
</footer>
<script src="./js/clock.js"></script>
<script src="./js/background.js"></script>
<script src="./js/greeting.js"></script>
</body>
</html>
시계와 인사를 표시할 태그와 인사에 들어가 이름값을 받을 input 태그를 만들어주었습니다. 배경이미지는 전체 화면에 나타내기 위해 body 태그에게 background-image 속성으로 나태낼 계획을 하고 하단에 명언을 표시하기 위해 태그를 추가하였습니다.
const background = document.querySelector("body");
const quote = document.querySelector(".quote");
const images = [
{
image: "image_1.jpg",
quote:
"고통이 너를 붙잡고 있는 것이 아니다. 네가 그 고통을 붙잡고 있는 것이다.",
},
{
image: "image_2.jpg",
quote:
"세상에는 비방만 받고, 칭찬만 받는 사람은 지난날에도 없었고 지금도 없으며, 앞으로도 없을 것이다.",
},
{
image: "image_3.jpg",
quote: "바다는 비에 젖지 않는다",
},
{
image: "image_4.jpg",
quote: "원하는 것을 얻지 못하는 것이 때로는 행운이라는 것을 명심하라.",
},
{
image: "image_5.jpg",
quote: " 다른 사람으로 인해 마음이 흔들려서는 안 됩니다.",
},
{
image: "image_6.jpg",
quote: "하나의 일이 모든 면에서 부정적인 경우는 거의 없습니다.",
},
{
image: "image_7.jpg",
quote:
"때로 자신이 원하는 것을 얻지 못하는 것이 행운일 수 있다는 것을 기억해야 합니다.",
},
{
image: "image_8.jpg",
quote: "때로는 침묵이 최고의 대답입니다.",
},
{
image: "image_9.jpg",
quote: "문제에 해법이 없다면 걱정으로 시간을 낭비하지 마세요.",
},
{
image: "image_10.jpg",
quote: "규칙은 잘 알아야 더욱 효과적으로 파괴할 수 있습니다.",
},
];
const getRandom = () => {
const randomNumber = Math.floor(Math.random() * images.length);
background.style.backgroundImage = `url("./images/${images[randomNumber].image}")`;
quote.innerText = images[randomNumber].quote;
};
getRandom();
배경이미지와 명언이 담긴 객체가 담긴 배열을 만들어주었습니다. 랜덤숫자를 생성하기 위해 Math 객체의 random 함수를 사용하였습니다. random 함수는 0 이상 1 미만의 부동소숫점 의사 난수를 반환하기 때문에 배경이미지와 명언이 담긴 객체가 담긴 배열의 length 값과 Math 객체의 floor 함수를 사용하여 0 이상 배열의 lenght 미만의 정수의 랜덤숫자를 구하여야 합니다. 해당 랜덤숫자를 이용하여 배열으로부터 랜덤한 객체의 배경이미지 url 과 명언을 구할 수 있습니다.
const greetingForm = document.querySelector(".greeting__form");
const greetingTitle = document.querySelector(".greeting__title");
const greetingInput = greetingForm.querySelector(".greeting__form__input");
const onGreeting = (event) => {
event.preventDefault();
const time = new Date().getHours();
let greetingMsg;
if (time >= 6 && time < 12) {
greetingMsg = `Good morning, ${greetingInput.value}.`;
} else if (time >= 12 && time < 18) {
greetingMsg = `Good afternoom, ${greetingInput.value}.`;
} else if (time >= 18 && time < 22) {
greetingMsg = `Good evening, ${greetingInput.value}.`;
} else {
greetingMsg = `Good night, ${greetingInput.value}.`;
}
greetingTitle.innerText = greetingMsg;
greetingInput.classList.add("hidden");
};
greetingForm.addEventListener("submit", onGreeting);
사용자의 이름을 받는 input 태그가 담긴 form 태그에게 addEventListener이용해 submit 이벤트를 받으면 onGreeting 함수를 실행시키게 만들어줍니다. 이때 form은 기본적으로 submit이 실행시 페이지의 reload가 발생되므로 preventDefault를 이용하여 해당 reload를 막아주어야 합니다. onGreeting 함수는 사용자의 이름을 받는 input의 value로 이름을 구하고 Date 객체의 getHours함수로 부터 현재 시간을 구해 조건문을 사용하여 인사말을 변경해줍니다. 그 후 미리 만들어둔 visibility 속성이 hidden인 class를 input에게 넣어주어 인사말이 나오는 동시에 input을 숨겨줍니다.
const clockContinaer = document.querySelector(".clock");
const clockTitle = clockContinaer.querySelector(".clock__title");
const getTime = () => {
const date = new Date();
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
const time = `${hours < 10 ? hours.toString().padStart(2, "0") : hours}:${
minutes < 10 ? minutes.toString().padStart(2, "0") : minutes
}:${seconds < 10 ? seconds.toString().padStart(2, "0") : seconds}`;
clockTitle.innerText = time;
};
setInterval(getTime, 1000);
getTime();
Date 객체로부터 시간, 분 그리고 초값을 구할 수 있습니다. 또한 시각적으로 보기 좋은 시계를 만들기 위해 시간, 분 및 초값이 10이하일 경우 삼항 연산자와 padStart를 이용하여 앞에 0을 추가하였습니다. 또한 1초 마다 시간을 바꾸기 위해 setInterval 함수를 이용하였습니다.
@import "./reset.css";
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;400;500;700&display=swap");
* {
box-sizing: border-box;
}
body {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-size: cover;
background-repeat: no-repeat;
font-family: "Noto Sans KR", sans-serif;
color: #fff;
}
main {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.hidden {
visibility: hidden;
}
.clock__title {
font-size: 160px;
font-weight: bold;
text-shadow: 1px 1px 5px rgba(0, 0, 0, 0.3);
}
.greeting {
text-align: center;
}
.greeting__title {
font-size: 42px;
font-weight: 500;
text-shadow: 1px 1px 5px rgba(0, 0, 0, 0.3);
}
.greeting__form {
margin-top: 30px;
text-align: center;
}
.greeting__form__input {
width: 350px;
padding: 10px 20px;
font-size: 32px;
color: #fff;
border: none;
text-shadow: 1px 1px 5px rgba(0, 0, 0, 0.3);
border-bottom: 2px solid #fff;
background-color: inherit;
}
.greeting__form__input:focus {
outline: none;
}
footer {
position: fixed;
bottom: 0;
}
.quote {
margin-bottom: 50px;
text-shadow: 1px 1px 5px rgba(0, 0, 0, 0.3);
}
대부분의 레이아웃을 flex를 이용하여 만들었습니다. 또한 hidden 이름을 가진 class 에서는 태그를 숨기는 class인데 display 속성의 none값 대신 visibility 속성의 hidden을 사용했습니다. 이는 display 속성의 none은 화면에 보이지 않게 처리하고 차지하고 있는 공간도 없어지기 때문에 레이아웃이 변경되지만 visibility 속성의 hidden은 화면에 보이지 않게 처리하지만 차지하고 있는 공간은 그대로 두어 레이아웃이 무너지지 않기 때문입니다.
바닐라 Javascript만을 이용하여 과제를 완성하였습니다. 강의 때 실습했던 내용과 거의 비슷한 내용의 과제였지만 string 값을 추가하는 방법에서 결과물은 같지만 다른 방식으로 결과물을 도출해보았습니다. 이렇듯 결과물을 만드는데 다양한 방법이 있고 어떤 방법이 효율적인지 대해 잘 생각해보아야겠습니다.
#프로젝트캠프 #프로젝트캠프후기 #유데미 #스나이퍼팩토리 #웅진씽크빅 #인사이드아웃 #IT개발캠프 #개발자부트캠프 #리액트 #react #부트캠프 #리액트캠프