[JavaScript - 실습] Random Lunch Slot

테크야끼·2021년 4월 22일
0

JavaScript

목록 보기
8/13
post-thumbnail

💡프로젝트 계획이유

JavaScript 학습 중, 지금까지 학습한 문법을 이용해 실생활에 밀접하게 관련된 간단한 프로젝트를 계획하고 싶다는 생각이 들었다. 프로젝트의 전체적인 아이디어를 고안하는 도중, 사람이라면 누구나 식사메뉴를 고민한다는 생각에 도달했다. 거기에 조금의 게임요소를 더해 랜덤으로 메뉴를 뽑는 요소를 더해 Random Lunch Slot을 제작하였다.

💡주요 로직

  • shuffle 메소드를 사용해, 미리 선언해놓은 배열의 순서를 랜덤하게 바꾼다.
  • onclick event를 사용해, 사용자가 버튼을 클릭하는 것 만으로 event가 실행되게한다.

💡코드

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Lunch Slot</title>
    <link rel="stylesheet" href="./css/style.css" />
    <script type="text/javascript" defer src="./js/common.js"></script>
  </head>
  <body>
    <div class="container">
      <div class="receipt">
        <div class="title_text">
          <h1>Lunch</h1>
          <h3>menu pick</h3>
        </div>
        <div class="menu_print">
          <h2></h2>
        </div>
        <div class="menu_slot">
          <div class="slot_container">
            <ul class="slide_box">
              <li>카레</li>
              <li>우동</li>
              <li>햄버거</li>
              <li>냉면</li>
              <li>마라탕</li>
            </ul>
          </div>
        </div>
        <div class="main_text">
          <p>DISTANCE<span>:??m</span></p>
          <p>COST&<em>:?000won</em></p>
          <p>LIKE<span>:♥♥♥♥♥</span></p>
          <br />
          <p>TOTAL<span>100% like it</span></p>
        </div>
        <div class="btn_area">
          <button onclick="lunchIs()">Pick menu</button>
          <button onclick="reset()">Reset</button>
        </div>
      </div>
    </div>
  </body>
</html>

CSS

@charset "UTF-8";
@import url("https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Orelega+One&display=swap");

* {
  padding: 0;
  margin: 0;
}

ul,
ol {
  list-style: none;
}

body {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.slot_container {
  width: 100px;
  height: 50px;
  overflow: hidden;
}

.menu_slot {
  position: absolute;
  top: 44%;
}

@keyframes slide {
  0% {
    margin-top: 0;
  }
  10% {
    margin-top: -50px;
  }
  20% {
    margin-top: -100px;
  }
  30% {
    margin-top: -150px;
  }
  40% {
    margin-top: -200px;
  }
  50% {
    margin-top: -250px;
  }
  60% {
    margin-top: -300px;
  }
  70% {
    margin-top: -350px;
  }
  80% {
    margin-top: -400px;
  }
  90% {
    margin-top: -450px;
  }
  100% {
    margin-top: -500px;
  }
}

.slide_box {
  width: 100px;
  height: 50px * 5;
  animation: slide 1.5s infinite;
  color: black;
}

.slide_box li {
  width: 100px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  font-weight: bold;
}

.container {
  margin: auto 0;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 300px;
  height: 400px;
}

.receipt {
  width: 100%;
  height: 100%;
  background-image: url("../img/paper.jpeg");
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: 30px;
  position: relative;
}

.receipt .title_text {
  border-bottom: 1px dashed black;
  width: 100%;
  text-align: center;
}

.receipt .title_text h1 {
  font-family: "Orelega One", cursive;
  font-size: 50px;
  margin-bottom: 0;
}

.receipt .title_text h3 {
  margin-bottom: 20px;
}

span,
em {
  display: inline-block;
  width: 78px;
  height: 21px;
  text-align: left;
  position: absolute;
  right: 5px;
}

.main_text p:last-child > span {
  width: 120px;
}

.menu_print {
  position: absolute;
  top: 40%;
  font-size: 40px;
  color: black;
  transition: 0.5s;
}

.receipt .main_text {
  font-family: "Roboto Mono", monospace;
  position: absolute;
  left: 30px;
  bottom: 5%;
}

.receipt .main_text p > em {
  font-style: normal;
}

p:last-child {
  border-top: 1px dashed black;
  padding-top: 10px;
  width: 250px;
}

.btn_area {
  position: absolute;
  bottom: -60px;
  margin-top: 20px;
}

body:before {
  content: "";
  display: inline-block;
  vertical-align: middle;
}
button {
  background: black;
  color: #fff;
  border: none;
  position: relative;
  height: 40px;
  font-size: 1.4em;
  padding: 0 1em;
  cursor: pointer;
  transition: 800ms ease all;
  outline: none;
  font-family: "Orelega One", cursive;
}
button:hover {
  background: #fff;
  color: black;
}
button:before,
button:after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  height: 2px;
  width: 0;
  background: black;
  transition: 400ms ease all;
}
button:after {
  right: inherit;
  top: inherit;
  left: 0;
  bottom: 0;
}
button:hover:before,
button:hover:after {
  width: 100%;
  transition: 800ms ease all;
}

JavaScript

//런치리스트 배열생성
let lunchList = ["떡볶이", "우동", "햄버거", "냉면", "마라탕"]

//배열복사
let firstLunchList = [];

lunchList.forEach(function(item) {
  firstLunchList.push(item);
});

let distanceList = ["10m", "8m", "7m", "7m", "9m"];
let costList = ["7000won", "5000won", "4500won", "8000won", "9000won"];


//제어할 요소선택 후 변수에 담기
let displaySlot = document.querySelector(".menu_slot"); //menu slot
let elem = document.querySelector(".menu_print > h2"); //menu print
let distanceTxt = document.querySelector(".main_text> p > span"); //distance
let costTxt = document.querySelector("em"); //cost


//reset check
let resetNum = 1;

//LunchIs 함수선언
function lunchIs() {
  //setTimeout 선언
  setTimeout(timeFunc, 900);

  function timeFunc() {
    //shuffle 메소드 선언
    function shuffle(a) {
      for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
      }
      return a;
    }

    //슬롯애니메이션 감추기
    displaySlot.style.display = "none";

    //shuffle 메소드를 사용하여 석은 배열에서 index[0]을 가져오기
    console.log(shuffle(lunchList));
    let lunckPick = shuffle(lunchList)[0];

    //메뉴 노출
    console.log(lunckPick);
    elem.innerHTML = lunckPick;

    //선택된 메뉴의 indexOf를 이용하여 distanceTxt, costTxt 노출
    
    
    let i = firstLunchList.indexOf(lunckPick);
    distanceTxt.innerHTML = distanceList[i];
    costTxt.innerHTML = costList[i];

    //reset 되었을 경우에 숨겨진 메뉴를 다시 노출시킴
    if (resetNum == 0) {
      elem.style.display = "block";
    }
  }
}

//reset 함수선언
function reset() {
  //메뉴 숨기기
  elem.style.display = "none";

  //슬롯애니메이션 노출
  displaySlot.style.display = "block";

  //distance, cost 초기화
  distanceTxt.innerHTML = "??m";
  costTxt.innerHTML = "?000won";

  //resetNum으로 reset여부를 구분하기 위해 0 할당
  resetNum = 0;
}

💡후기

👍    음식명에서 부터 음식,식당같은 관련 단어를 연상하다가 영수증이라는 키워드가 떠올랐는데, 심플하게 정보전달을 하는 영수증의 목적과 레트로 느낌의 폰트를 적용하여 로직과 어울리는 디자인을 css로 구현할 수 있어서 만족스러웠다.

🤷‍♀️    Random Lunch Slot은 shuffle()을 이용해 배열의 순서를 랜덤으로 바꿨는데, 출력되는 값은 배열의 값 하나이기 때문에 shuffle()이 아닌, Math.random()을 이용해 난수를 만드는 것이 간략하고 목적에 맞는 코드를 만드는 문법일 수 있다고 생각했다.


점심메뉴 정하러 가기

1개의 댓글

comment-user-thumbnail
2022년 5월 4일

안녕하세요 질문이 있습니다. 메뉴 끝나고 딜레이가 있는데요~ 스크립트 수정할 수 있는 구조인가요?

답글 달기