CGV Mobile

CHOI-syΒ·2023λ…„ 12μ›” 27일
0

ν”„λ‘œμ νŠΈ

λͺ©λ‘ 보기
3/5
post-thumbnail

πŸ’» CGV Mobile

  • μ‚¬μ΄νŠΈλͺ…: CGV Mobile
  • μ‚¬μš©μ–Έμ–΄: HTML, CSS, JavaScript
  • 라이브러리: jQuery,Swiper,JSON
  • μœ ν˜•: Mobileμ μ‘ν˜•
  • πŸ“° https://hallowmang.github.io/CGV-Mobile/

βœ… Check Point

βœ” header
βœ” νƒ­μ „ν™˜
βœ” Swiper
βœ” μ•„μ½”λ””μ–Έ
βœ” fetch() ν•¨μˆ˜λ₯Ό ν™œμš© json데이터λ₯Ό 호좜


1.header

πŸ“ κΈ°μ‘΄ λͺ¨λ°”일 cgvλŠ” 크기에 맞좰 쀄어듀어든 반면, overflow: autoλ₯Ό μ‚¬μš©ν•˜μ—¬, ν™”λ©΄ λ°–μœΌλ‘œ λ‚˜κ°€κ²Œ 되면 μŠ€ν¬λ‘€μ„ ν•  수 μžˆλŠ” μ˜μ—­μœΌλ‘œ λ§Œλ“€μ—ˆλ‹€

.nav {
      overflow: auto;
      background: linear-gradient(to left,#ef642f,#fb4357);
}

πŸ”΄ κΈ°μ‘΄ λͺ¨λ°”일 CGV

πŸ‘‰ μž‘μ—…ν•œ CGV


2.νƒ­ μ „ν™˜β­β­

λ¬΄λΉ„μ°¨νŠΈ, μƒμ˜μ˜ˆμ •μ„ λˆ„λ₯΄λ©΄ λ°‘μ˜ μ½˜ν…Œμ΄λ„ˆκ°€ μ „ν™˜ν•˜λŠ” 것을 ν•˜κ³  μ‹Άμ—ˆλ‹€. μ˜ν™” μ•± λΏλ§Œμ•„λ‹ˆλΌ, λ‹€μ–‘ν•œ ν™ˆνŽ˜μ΄μ§€μ—μ„œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—,
μ—„μ²­λ‚˜κ²Œ μ€‘μš”ν•˜λ‹€κ³  μƒκ°ν–ˆλ‹€.

κΌ­ μ•Œμ•„λ‘μž!!!

	.container-chart{
        display: none;
        /*μ΄ν•˜μƒλž΅*/
        &.active{
          display: block;
        }
      }
    .container-soon{
        display: none;
        /*μ΄ν•˜μƒλž΅*/
        &.active{
          display: block;
        }
      }
// .title-wrap 클래슀 μ•ˆμ— μžˆλŠ” .name 클래슀λ₯Ό 가진 μš”μ†Œκ°€ ν΄λ¦­λ˜μ—ˆμ„ λ•Œ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜
$('.title-wrap .name').click(function(){
    // 클릭된 μš”μ†Œμ˜ data-container 속성 값을 가져와 containerName λ³€μˆ˜μ— ν• λ‹Ή
    containerName = $(this).data('container')
    
    // 클릭된 μš”μ†Œμ— 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜κ³ , ν˜•μ œ μš”μ†Œλ“€μ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜μ—¬ 선택 μš”μ†Œλ§Œ ν™œμ„±ν™”
    $(this).addClass('active').siblings().removeClass('active')
    
    // containerName에 ν•΄λ‹Ήν•˜λŠ” μš”μ†Œμ— 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜κ³ , ν˜•μ œ μš”μ†Œλ“€μ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜μ—¬ ν•΄λ‹Ή μ»¨ν…Œμ΄λ„ˆλ§Œ ν™œμ„±ν™”
    $(containerName).addClass('active').siblings().removeClass('active');
})

$(this).addClass('active').siblings().removeClass('active')λŠ” 클릭된 탭에 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜μ—¬ ν•΄λ‹Ή 탭을 ν™œμ„±ν™”ν•˜κ³ , λ‹€λ₯Έ 탭은 λΉ„ν™œμ„±ν™” 이 뢀뢄은 νƒ­ λ©”λ‰΄μ—μ„œ ν˜„μž¬ μ„ νƒλœ 탭을 κ°•μ‘°ν•˜κ³ , λ‹€λ₯Έ 탭듀을 λΉ„ν™œμ„±ν™”ν•˜λŠ” 역할을 ν•œλ‹€.

$(containerName).addClass('active').siblings().removeClass('active');은 μ‹€μ œ νƒ­κ³Ό μ—°κ²°λœ 컨텐츠λ₯Ό ν™œμ„±ν™”ν•˜κ³ , λ‹€λ₯Έ μ»¨ν…μΈ λŠ” λΉ„ν™œμ„±ν™”ν•©λ‹ˆλ‹€. 이 뢀뢄은 탭에 ν•΄λ‹Ήν•˜λŠ” 컨텐츠λ₯Ό 화면에 λ‚˜νƒ€λ‚΄κ±°λ‚˜ μ‚¬λΌμ§€κ²Œ ν•˜μ—¬ μ‚¬μš©μžμ—κ²Œ μ„ νƒλœ νƒ­μ˜ λ‚΄μš©μ„ λ³΄μ—¬μ£ΌλŠ” μ—­ν• 

즉, 두 쀄이 ν•¨κ»˜ λ™μž‘ν•˜μ—¬ νƒ­ κ°„ μ „ν™˜ 효과λ₯Ό λ§Œλ“ λ‹€. ν•˜λ‚˜λ§Œ 있으면 νƒ­μ˜ 선택 μƒνƒœλŠ” λ³€κ²½λ˜μ§€λ§Œ, μ‹€μ œ μ»¨ν…μΈ μ˜ μ „ν™˜μ€ 이루어지지 μ•Šμ„ 수 μžˆλ‹€.

예맀차트, ν˜„μž¬μƒμ˜μž‘, ICECON 등도 λ§ˆμ°¬κ°€μ§€λ‘œ 같은 λ°©μ‹μœΌλ‘œ ν•˜μ˜€λ‹€.

$('.hash-item').click(function(e){
    e.preventDefault();

    // 클릭된 μš”μ†Œμ˜ data-list 속성 값을 가져와 tabName λ³€μˆ˜μ— ν• λ‹Ή
    tabName = $(this).data('list');

    // 클릭된 μš”μ†Œμ— 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜κ³ , ν˜•μ œ μš”μ†Œλ“€μ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜μ—¬ 선택 μš”μ†Œλ§Œ ν™œμ„±ν™”
    $(this).addClass('active').siblings().removeClass('active');

    // tabName에 ν•΄λ‹Ήν•˜λŠ” μš”μ†Œμ— 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜κ³ , ν˜•μ œ μš”μ†Œλ“€μ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜μ—¬ ν•΄λ‹Ή νƒ­ λ‚΄μš©λ§Œ ν™œμ„±ν™”
    $(tabName).addClass('active').siblings().removeClass('active');
})

3.Swiper

cgv λͺ¨λ°”일에 Swiperκ°€ 많이 μ‚¬μš©λ˜μ—ˆλ‹€.
πŸ”μ‚¬μ΄νŠΈ - https://swiperjs.com/

βœ… slidesPerView
Swiperμ˜΅μ…˜μ€‘μ— ν•˜λ‚˜μΈ slidesPerViewλŠ” λ ˆμ΄μ•„μ›ƒμ˜ 뷰의 개수λ₯Ό μ„€μ •ν•œλ‹€
βœ… spaceBetween⭐
Swiper은 CSS에 μ§μ ‘μ μœΌλ‘œ paddingμ΄λ‚˜ margin을 μ£ΌλŠ” 것을 μ•ˆ μ’‹μ•„ν•œλ‹€
κ·Έλž˜μ„œ μ‚¬μš©ν•˜λŠ” 것이 Swiperμ˜΅μ…˜ spaceBetween으둜 여백을 μ£Όλ©΄ λœλ‹€.

const contentSlide = new Swiper('.swiper.content-group',{
 slidesPerView:"auto",
 spaceBetween:10,
});

πŸ‘‰ 적용 μ‹œ

λ§Œμ•½μ—, slidesPerViewλ₯Ό μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄,

여백이 많이 λ‚¨μœΌλ©°, μŠ¬λΌμ΄λ“œκ°€ λκΉŒμ§€ κ°€λ©΄, μŠ¬λΌμ΄λ“œκ°€ μ•ˆλ˜λŠ” ν˜„μƒμ΄ λ°œμƒν•œλ‹€. λ˜ν•œ spaceBetween도 적용이 μ•ˆλ˜μ—ˆλ‹€.

그리고 μŠ€μ™€μ΄νΌλ₯Ό μ‚¬μš©ν•˜λ©΄, CSS에 μ§μ ‘μ μœΌλ‘œ paddingμ΄λ‚˜ margin을 주지 μ•Šλ„λ‘ μ£Όμ˜ν•˜μž!!


4.μ•„μ½”λ””μ–Έ

아코디언은 μ•„μ½”λ””μ–Έμ²˜λŸΌ μœ„μ•„λž˜λ‘œ μ›€μ§μ΄λŠ” μ• λ‹ˆλ©”μ΄μ…˜ λ•Œλ¬Έμ— 뢙여진 이름같닀.(λ‡Œν”Όμ…œ)
아코디언을 μ“°λ©΄ 정말 멋진 μ• λ‹ˆλ©”μ΄μ…˜μ€ μ•„λ‹ˆμ§€λ§Œ 정말 μœ μš©ν•˜κ²Œ μ“°μΌλ§Œν•œ μ• λ‹ˆλ©”μ΄μ…˜κ°™λ‹€. μ•Œμ•„λ‘λ©΄ 쒋을듯!!

λ¨Όμ € 아코디언을 μ ‘μ–΄λ‘” μƒνƒœ

$('.cinema-title').click(function(e){
    e.preventDefault();

    // 클릭된 μš”μ†Œκ°€ 'active' 클래슀λ₯Ό 가지고 μžˆλŠ”μ§€ 확인
    if ($(this).hasClass('active')) {
        // λ§Œμ•½ 클릭된 μš”μ†Œκ°€ 'active' 클래슀λ₯Ό 가지고 μžˆλ‹€λ©΄,
        // 'cinema-title' 클래슀λ₯Ό 가진 λͺ¨λ“  μš”μ†Œμ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜κ³ ,
        // 'cinema-imgbox' 클래슀λ₯Ό 가진 ν˜•μ œ μš”μ†Œλ“€μ„ μœ„λ‘œ μˆ¨κΉ€(slides up)
        $('.cinema-title').removeClass('active').siblings('.cinema-imgbox').slideUp();
    } else {
        // 클릭된 μš”μ†Œκ°€ 'active' 클래슀λ₯Ό 가지고 μžˆμ§€ μ•Šλ‹€λ©΄,
        // 'cinema-title' 클래슀λ₯Ό 가진 λͺ¨λ“  μš”μ†Œμ˜ 'active' 클래슀λ₯Ό μ œκ±°ν•˜κ³ ,
        // 'cinema-imgbox' 클래슀λ₯Ό 가진 ν˜•μ œ μš”μ†Œλ“€μ„ μœ„λ‘œ μˆ¨κΉ€(slides up)
        $('.cinema-title').removeClass('active').siblings('.cinema-imgbox').slideUp();
        
        // ν˜„μž¬ 클릭된 μš”μ†Œμ— 'active' 클래슀λ₯Ό μΆ”κ°€ν•˜κ³ ,
        // 'cinema-imgbox' 클래슀λ₯Ό 가진 ν˜•μ œ μš”μ†Œλ“€μ„ μ•„λž˜λ‘œ λ‚˜νƒ€λƒ„(slides down)
        $(this).addClass('active').siblings('.cinema-imgbox').slideDown();
    }
})

πŸ“ .cinema-titleλ₯Ό 클릭 ν–ˆμ„ λ•Œ, .activeκ°€ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό 보고 ν˜•μ œμš”μ†ŒμΈ .cinema-imgboxλ₯Ό μœ„λ‘œ μˆ¨κΈ°κ±°λ‚˜(slides up) μ•„λž˜λ‘œ λ‚˜νƒ€λƒ„(slides down)

❗❗⭐⭐ λ§Œμ•½ else블둝에 μžˆλŠ” $('.cinema-title').removeClass('active').siblings('.cinema-imgbox').slideUp();κ°€ μ—†μœΌλ©΄
λ‹€λ₯Έ .cinema-titleλ₯Ό 클릭해도 계속 μ—΄λ¦°μƒνƒœλ‘œ μœ μ§€λ˜λ‹ˆ κΌ­ μΆ”κ°€ν•΄μ£Όμž~


5. fetch 비동기톡신 ν™œμš©

πŸ‘‰ 적용
예맀차트, ν˜„μž¬μƒμ˜μž‘ ~ CGV Only λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ λΆ„λ₯˜λœ 데이터λ₯Ό 뢈러올 수 μžˆλ„λ‘ ν•˜μ˜€λ‹€.

1. json νŒŒμΌμ„ λ§Œλ“€μ–΄ 뢈러올 데이터 λ§Œλ“€κΈ°

μΉ΄ν…Œκ³ λ¦¬λ³„λ‘œ λΆ„λ₯˜ν•˜κΈ° μœ„ν•΄ chartList,currentList,onlyList둜 λ‚˜λˆ„μ–΄ νŒŒμΌμ„ λ§Œλ“€μ—ˆλ‹€.

{
"chartList": [
    {
      "id": 0,
      "age": "All",
      "cgvOnly": false,
      "rank": 1,
      "thumbNail": "https://img.cgv.co.kr/Movie/Thumbnail/Poster/000087/87433/87433_320.jpg",
      "type": {
        "iMax": true,
        "4DX": false,
        "screenX": false
      },
      "title": "κ·ΈλŒ€λ“€μ€ μ–΄λ–»κ²Œ μ‚΄ 것인가",
      "rate": {
        "adv": "26.9%",
        "egg": "99%"
      },
      "view": null,
      "dDay": "D-7"
    },
    /*μ΄ν•˜μƒλž΅*/
  ],
  "currentList":[
    {
      "id":0,
      "age":"All",
      "cgvOnly":true,
      "rank":1,
      "thumbNail":"https://img.cgv.co.kr/Movie/Thumbnail/Poster/000087/87422/87422_320.jpg",
      "type":{
        "iMax":false,
        "4DX":false,
        "screenX":true
      },
      "title":"λ°”λžŒ 따라 λ§Œλ‚˜λ¦¬ : κΉ€ν˜Έμ€‘μ˜ κ³„μ ˆ",
      "rate":{
        "adv":"13.1%",
        "egg":"92%"
      },
      "view":170,
      "dDay":null
    },
    /*μ΄ν•˜μƒλž΅*/
  ],
  "iceconList":[
   /*μƒλž΅*/
  ],
  "artList":[
   /*μƒλž΅*/
  ],
  "onlyList":[
    {
      "id":0,
      "age":"All",
      "cgvOnly":true,
      "rank":1,
      "thumbNail":"https://img.cgv.co.kr/Movie/Thumbnail/Poster/000087/87500/87500_320.jpg",
      "type":{
        "iMax":false,
        "4DX":false,
        "screenX":false
      },
      "title":"νŒ€ λ²„νŠΌμ˜ 크리슀마슀 μ•…λͺ½",
      "rate":{
        "adv":"3.2%",
        "egg":"?"
      },
      "view":"5.4만",
      "dDay":null
    },
    /*μ΄ν•˜ μƒλž΅*/
  ]
    }

2. 데이터 뢈러였기

fetch('./assets/data/movie.json')
.then(res=>res.json())
.then(json=>{
  // λ‹€μ–‘ν•œ μΉ΄ν…Œκ³ λ¦¬μ— ν•΄λ‹Ήν•˜λŠ” 데이터듀을 λ³€μˆ˜μ— μ €μž₯
  const booking = json.chartList; // 예맀차트 데이터
    const current = json.currentList; // ν˜„μž¬ μƒμ˜μž‘ 데이터
    const iceCon = json.iceconList; // μ–ΌμŒκ΄€ 데이터
    const artHouse = json.artList; // μ•„νŠΈν•˜μš°μŠ€ 데이터
    const cgvOnly = json.onlyList; // CGV Only 데이터
  
  /* 예맀차트 */
  let bookingHtml = ``; // μ˜ˆλ§€μ°¨νŠΈμ— λŒ€ν•œ HTML을 μ €μž₯ν•  λ³€μˆ˜
    // 예맀차트 데이터λ₯Ό μˆœνšŒν•˜λ©΄μ„œ HTML을 생성
    booking.forEach(() => {
      // μ—¬κΈ°μ„œ 예맀차트 데이터λ₯Ό μ΄μš©ν•˜μ—¬ HTML μƒμ„±ν•˜λŠ” μ½”λ“œκ°€ λ“€μ–΄κ°„λ‹€.
      bookingHtml += 
        `<li class="swiper-slide content-item">
    <div class="movie-poster">
      <a class="detail-link" href="#"></a>
      <div class="asdf">
        <div class="onlyage-wrap">
          ${only}
          <div class="screen-type">
            <img src="${screenTypeImage}" alt="" style="${displayStyle}">
          </div>
          <i class="age age${element.age}">
            <span class="blind">
              12μ„Έκ΄€λžŒκ°€
            </span>
          </i>
        </div>
        <img src="${element.thumbNail}" alt="">
        <span class="ranking">
          <span class="rank-img">
            <img src="./assets/images/ranknum${element.rank}.png" alt="">
          </span>
          <span class="per">${element.rate.adv}</span>
        </span>
      </div>
    </div>
/* μ΄ν•˜μƒλž΅ */
`
    });
  
  /* ν˜„μž¬μƒμ˜μž‘ */
    let currentHtml = ``; // ν˜„μž¬μƒμ˜μž‘μ— λŒ€ν•œ HTML을 μ €μž₯ν•  λ³€μˆ˜
    // ν˜„μž¬μƒμ˜μž‘ 데이터λ₯Ό μˆœνšŒν•˜λ©΄μ„œ HTML을 생성
    current.forEach(() => {
      // ν˜„μž¬μƒμ˜μž‘ 데이터λ₯Ό μ΄μš©ν•˜μ—¬ HTML μƒμ„±ν•˜λŠ” μ½”λ“œκ°€ λ“€μ–΄κ°„λ‹€.
      currentHtml += `μœ„μ˜ 방식과 λΉ„μŠ·ν•¨`
    });

  .
  .							/* μƒλž΅ */
  .
  
  /* cgv only */
  let cgvOnlyHtml = ``; // CGV μ „μš©μ— λŒ€ν•œ HTML을 μ €μž₯ν•  λ³€μˆ˜
    // CGV Only 데이터λ₯Ό μˆœνšŒν•˜λ©΄μ„œ HTML을 생성
    cgvOnly.forEach(() => {
      // CGV Only 데이터λ₯Ό μ΄μš©ν•˜μ—¬ HTML μƒμ„±ν•˜λŠ” μ½”λ“œκ°€ λ“€μ–΄κ°„λ‹€.
      cgvOnlyHtml += `μœ„μ˜ 방식과 λΉ„μŠ·ν•¨`
    });
}

${only}λŠ” λ°μ΄ν„°νŒŒμΌμ—μ„œ cgvOnlyκ°€ true, false에 λ”°λΌμ„œ λ‚˜μ˜€κΈ° λ•Œλ¬Έμ— 쑰건식을 μ‚¬μš©ν–ˆλ‹€.

onlyEl = `
  <div class="only-box">
    <img src="https://img.cgv.co.kr/Movie/Thumbnail/PosterIcon/16231991733190.png" alt="" style="">
  </div>
`;

// `element.cgvOnly`κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•œ 후에 쑰건에 따라 `only` λ³€μˆ˜μ— ν• λ‹Ή
// `element.cgvOnly`κ°€ μ‘΄μž¬ν•˜λ©΄ `onlyEl` λ³€μˆ˜μ˜ 값을 ν• λ‹Ήν•˜κ³ , 그렇지 μ•ŠμœΌλ©΄ 빈 λ¬Έμžμ—΄μ„ ν• λ‹Ήν•©λ‹ˆλ‹€.
let only = element.cgvOnly ? onlyEl : "";

${screenTypeImage}λŠ” 슀크린이 iMax, 4DX, screenX에 λ”°λΌμ„œ λ‚˜μ˜€λŠ” 이미지가 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— 쑰건에 따라 이미지 URL을 ν• λ‹Ήν•˜κ±°λ‚˜ null 값을 ν• λ‹Ήν•  수 있게 쑰건식을 μ‚¬μš©ν–ˆλ‹€.

// 각 쑰건은 νŠΉμ • μ’…λ₯˜μ˜ μ˜ν™” 슀크린 νƒ€μž…μ— 따라 λ‹€λ₯Έ 이미지λ₯Ό μ‚¬μš©
let screenTypeImage =
  element.type && element.type.iMax
    ? "https://img.cgv.co.kr/WebApp/images/main/@3x/ico_screenType0.png"
    : element.type && element.type["4DX"]
    ? "https://img.cgv.co.kr/WebApp/images/main/@3x/ico_screenType1.png"
    : element.type && element.type.screenX
    ? "https://img.cgv.co.kr/WebApp/images/main/@3x/ico_screenType2.png"
    : null;

// `screenTypeImage` λ³€μˆ˜μ— 이미지 URL이 μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜μ—¬ `displayStyle` λ³€μˆ˜μ— CSS μŠ€νƒ€μΌμ„ μ„€μ •
// 이미지 URL이 μ‘΄μž¬ν•˜λ©΄ 빈 λ¬Έμžμ—΄μ„, 그렇지 μ•ŠμœΌλ©΄ 'display: none;' μŠ€νƒ€μΌμ„ ν• λ‹Ή
let displayStyle = screenTypeImage ? '' : 'display: none;';

μ΄λŸ°μ‹μœΌλ‘œ λͺ¨λ“  μΉ΄ν…Œκ³ λ¦¬μ— 쑰건식이 ν•„μš”ν•œ 뢀뢄을 μ μš©ν•΄μ„œ 데이터λ₯Ό λΆˆλ €λ‹€.

profile
μ•ˆλ…•ν•˜μ„Έμš”.

0개의 λŒ“κΈ€