[VanillaJS] 영화관 좌석 예약 페이지 만들기

초코침·2023년 3월 8일
64

VanillaJS

목록 보기
3/7

와이어 프레임

드롭박스에 영화 목록을 보여주고 좌석 배치도에는 자리 하나 하나를 클릭해서 차지할 수 있도록 한다. 차지한 좌석 개수만큼 총 가격을 보여준다.

기능 목록

  1. 영화 선택 기능

    • 선택한 영화 이름 알기 -> localStorage
    • 선택한 영화의 가격 알기 -> localStorage
  2. 좌석 선택 기능

    • 선택한 좌석 목록 알기 -> localStorage
    • 좌석 선택 시 해당 좌석 색상 파란색으로 변경
    • 좌석 선택 해제 시 해당 좌석 색상 회색으로 변경
  3. 선택한 좌석 개수와 가격 표시 기능

    • 선택한 좌석 개수 구하기 -> localStorage
    • 총 가격 구하기 -> localStorage
  4. localStorage에서 가져와 새로고침해도 유지되는 기능

완성본

완성본(Github) 바로가기

배운점

요소 회전 시키기 (영화관 스크린 만들기)

요소를 회전시켰을 때 원근감이 느껴도록 하려면 rotateperspective를 함께 사용해야 한다.

영화관 스크린이 실제로 벽에 붙어 있는 것 같은 효과를 주기 위해 회전 효과가 필요했는데 rotateX 뿐만 아니라, 다음처럼 스크린을 감싸는 부모 요소perspective라는 프로퍼티를 추가해줘야 했다.

그 이유는 perspective원근감을 결정하기 때문!

  • 코드
    <!DOCTYPE html>
    <html lang="en">
      <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" />
        <style>
          body {
            background-color: #242333;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
          }
          .container {
            perspective: 100px;
            perspective: 1000px;
          }
          .screen {
            width: 200px;
            height: 80px;
            background-color: white;
            box-shadow: 0 3px 10px rgba(255, 255, 255, 0.7);
          }
          .screen:hover {
            transition: all 3s ease-out;
            transform: rotateX(-180deg);
          }
        </style>
        <title>Document</title>
      </head>
      <body>
        <div class="container">
          <div class="screen"></div>
        </div>
      </body>
    </html>
  • perspective를 설정하지 않은 경우
    요소가 회전한다는 느낌보다는 세로폭이 줄어들었다가 다시 늘어나는 느낌이다.

  • perspective: 100px
    perspective가 작을수록 요소가 회전하는 걸 가까이서 보는 느낌이고

  • perspective: 1000px
    perspective가 클수록 요소가 회전하는 것을 멀리서 보는 느낌이다.

좌석에 hover 시 크기 변경하기

해당 좌석에 커서를 올렸을 때, 클릭하면 해당 좌석을 선택할 수 있다는 것을 시각적으로 표현해 주기 위해 좌석의 크기가 미세하게 커지도록 구현해야 했다.

이 부분은 transformscale로 구현할 수 있었다.

transform: scale({배수})

이미 예매된 좌석(occupied)이 아닌 좌석에 커서를 올렸을 때 좌석의 크기가 1.2배로 확대된다.

.seat:not(.occupied):hover {
  cursor: pointer;
  transform: scale(1.2);
}

좌석 클릭 시 좌석 색상 변경하기

예매 가능한 좌석을 클릭하면 하늘색을 색상을 변경해야 했는데, 이는 containstoggle의 조합으로 구현했다.

classList.contains()

해당 노드에 해당 클래스가 있는지 확인하기 위한 메서드다.

<div class="sample">sample div</div>
const div = document.querySelector('.sample');

if(div.classList.contains('sample')) { // true 리턴
	console.log('샘플 클래스 보유'); 
}
if(div.classList.contains('not-sample')) { // false 리턴
	console.log('샘플 클래스 미보유');
}

classList.toggle()

해당 노드에 해당 클래스가 있다면 제거하고 없다면 추가하는 메서드다.

<div class="sample">sample div</div>
const div = document.querySelector('.sample');

if(div.classList.contains('sample')){
	div.classList.toggle('selected'); // selected가 없다면 추가하고 있다면 제거한다.
}

프로젝트 코드

containerclick 이벤트 리스너를 달고 클릭한 요소가 좌석이고(contains(’seat’)), 이미 예매된 좌석이 아닌지(!contains(’occupied’)) 확인한다.

위 조건을 통과하면서 selected가 없다면(빈 좌석 선택) selected를 넣어주고, selected가 있다면(좌석 선택 해제) selected를 제거한다.

// Seat click event
container.addEventListener('click', (event) => {
  // classList로 해당 DOM이 가진 class 목록을 확인할 수 있음
  if (event.target.classList.contains('seat') && !event.target.classList.contains('occupied')) {
    // toggle로 classList에 해당 클래스명이 있다면 제거하고 없다면 추가
    event.target.classList.toggle('selected'); // 좌석 색깔이 파란색으로 변경됨

    updateSelectedCount();
  }
});

localStorage 사용하기

저장하기

로컬 스토리지에 데이터를 저장하는 작업은 localStorage.setItem으로 할 수 있다.

localStorage.setItem('keyName', 'values');

원시 값이 아닌 참조 값(배열, 객체 등)을 저장하는 경우에는 JSON 형식으로 바꿔주고 저장하는 것이 좋다.

localStorage.setItem('keyName', JSON.stringify({참조 자료형});

가져오기

로컬 스토리지에 저장한 데이터를 가져오는 작업은 localStorage.getItem으로 할 수 있다.

const value = localStorage.getItem('keyName');

JSON 형식으로 저장한 데이터를 가져오기 위해서는 파싱을 해야 한다.

const value = localStorage.getItem(JSON.parse({JSON 형식 데이터}));

더 공부해야할 것

계속 예제 많이 풀어보면서 DOM 조작하는 법을 더 익혀야겠다. 아직은 좀 헷갈린다.

profile
블로그 이사중 🚚 (https://sungjihyun.vercel.app)

3개의 댓글

comment-user-thumbnail
2023년 3월 14일

완성도가 뛰어나네요. 잘 봤습니다!

답글 달기
comment-user-thumbnail
2023년 3월 17일

멋져요

답글 달기
comment-user-thumbnail
2023년 3월 18일

디자인 이쁘네용

답글 달기