🍪 카카오 테크 캠퍼스 2기

[카카오 테크 캠퍼스 2기] 1단계 4주차 WIL - 스타벅스 예제 클론하기(4)

kangkibong 2024. 5. 3. 19:16

🔟 고정 이미지 배경

.pick-your-favorite {
  background-image: url('../images/favorite_bg.jpg');
  background-repeat: no-repeat;
  background-position: center;
  /* scroll시 배경화면이 멈춰있도록 하는 속성 => Parallax */
  background-attachment: fixed;
  background-size: cover;
}
  • background-attachment를 통해 배경이미지를 viewport를 기준으로 출력하도록 설정한다.
  • background-attachment: fixed로 설정하면, 스크롤시 배경화면이 멈춰있도록 스타일링할 수 있다.(Parallax)

 

 

1️⃣ 3D 애니메이션

메달을 hover했을때 앞, 뒷면이 뒤집어지는 애니메이션을 구현하려고 한다.

 

메달의 앞, 뒷면 구조 작성하기

메달의 앞, 뒷면에 해당하는 요소의 구조를 잡기 위해 다음과 같이 작성하였다.

<section class="reserve-store">
  <div class="inner">
    <div class="medal">
      <div class="front">
        <img src="./images/reserve_store_medal_front.png" alt="" />
      </div>
      <div class="back">
        <img src="./images/reserve_store_medal_back.png" alt="" />
        <a href="javascript:void(0)" class="btn">매장 안내</a>
      </div>
    </div>
  </div>
</section>

 

메달의 3D 애니메이션 적용하기

.reserve-store .medal {
  width: 334px;
  height: 334px;
  **perspective: 600px;**
}

.reserve-store .medal .front,
.reserve-store .medal .back {
  position: absolute;
  width: 334px;
  height: 334px;
  **backface-visibility: hidden;**
  transition: 1s;
}

.reserve-store .medal .front {
  transform: rotateY(0);
}

.reserve-store .medal:hover .front {
  transform: rotateY(180deg);
}

.reserve-store .medal .back {
  transform: rotateY(-180deg);
}

.reserve-store .medal:hover .back {
  transform: rotateY(0);
}

.reserve-store .medal:hover .back .btn {
  position: absolute;
  top: 248px;
  left: 0;
  right: 0;
  margin: auto;
}

 

  • 앞면(.front)에 rotateY0으로 설정하여 초기 Y각도를 명시적으로 작성한다.
  • 뒷면(.back)에 rotateY-180deg로 설정하여 초기 Y각도를 명시적으로 작성한다.
  • 앞면(.front)과 뒷면(.back)이 .medal에 겹쳐 질 수 있도록 positionabsolute로 설정한다.
  • 앞면(.front)과 뒷면(.back)을 backface-visibility: hidden으로 설정하여 하나가 뒤집어진 상태인 경우 숨기도록 설정한다.
  • 앞면(.front)를 hover했을 경우 rotateY180deg로 설정하여 오른쪽으로 뒤집어지도록 설정한다.
  • 뒷면(.back)을 hover했을 경우 rotateY0으로 설정하여 왼쪽으로 뒤집어지도록 설정한다.
  • .medal의 3D 애니메이션의 원근감을 주기 위해 perspective를 설정해준다.

 

결과

 

 

 

2️⃣ 스크롤 위치 계산 애니메이션

화면의 요소들이 스크롤할때 보여질 경우 위치를 다이나믹하게 움직여 나타낼 수 있도록 구현할 예정이다.

 

ScrollMagic

원하는 section이 화면에 보여지는지에 대한 여부를 ScrollMagic 외부 라이브러리를 통해 쉽게 알 수 있다.

 

 

 

ScrollMagic - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

The javascript library for magical scroll interactions. - Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests each month, powered by Cl

cdnjs.com

 

CDN 추가하기

<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js" defer>

 

감시할 섹션들 지정하기

<section class="season-product scroll-spy"></section>
<section class="reserve-coffee scroll-spy"></section>
<section class="pick-your-favorite scroll-spy"></section>
<section class="find-store scroll-spy"></section>

 

감시 요소 트리거 및 클래스 토글링

const spyEls = document.querySelectorAll('section.scroll-spy');
spyEls.forEach(spyEl => {
  new ScrollMagic.Scene({
    triggerElement: spyEl, 
    triggerHook: 0.8, 
  })
    .setClassToggle(spyEl, 'show')
    .addTo(new ScrollMagic.Controller());
});

 

  • section태그에 .scroll-spy 클래스를 가지는 감시하는 섹션들을 정의하고 forEach()를 통해 각 섹션들을 순회한다.
  • ScrollMagic객체에 Scene() 메서드를 통해 감시하는 섹션을 트리거하고 80% 영역에 도달하면 class가 토글링되도록 설정한다.
  • setClassToggle() 메서드를 통해 토글링할 클래스 .show를 설정한다.
  • addTo() 메서드를 통해 컨트롤러 내용을 추가한다.

 

 

감시하는 섹션들의 영역에서 80%가 넘어가는 순간 .show가 토글되는 것을 확인할 수 있다.

 

.show 및 위치 이동 클래스 정의하기

.back-to-position {
  opacity: 0;
  transition: 1s;
}

.back-to-position.to-right {
  transform: translateX(-150px);
}

.back-to-position.to-left {
  transform: translateX(150px);
}

.show .back-to-position {
  opacity: 1;
  transform: translateX(0);
}

 

  • .back-to-position 클래스를 통해 초기에는 안보이도록 opacity0으로 설정하고 transition을 통해 위치 이동시 1초의 딜레이 애니메이션을 준다.
  • .to-right 클래스를 가지면 맨 왼쪽으로 -150px로 초기에 배치되도록 한다.
  • .to-left 클래스를 가지면 맨 오른쪽으로 150px로 초기에 배치되도록 한다.
  • .show 클래스가 토글되면 요소들이 보여지도록 opacity1로 설정하고 초기 위치인 translateX0으로 설정한다.

 

결과

 

 

 

3️⃣ 페이지 상단으로 이동(ScrollTo)

페이지에 페이지의 최상단으로 이동하는 버튼을 생성한다.

추가로 페이지의 최상단으로 이동되면 페이지에서 사라지고 스크롤될 경우 버튼이 보이도록 할 예정이다.

이를 구현하기 위해 기존에 사용했던 gsap 라이브러리의 ScrollTo를 사용하여 구현해볼 예정이다.

 

GSAP - ScrollTo Plugin CDN 가져오기

 

 

gsap - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

GSAP is a JavaScript library for building high-performance animations that work in **every** major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch! No other library delive

cdnjs.com

 

위 사이트에서 ScrollToPlugin에 해당하는 cdn을 복사해서 head에 script로 가져온다.

 

 

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollToPlugin.min.js" integrity="sha512-1PKqXBz2ju2JcAerHKL0ldg0PT/1vr3LghYAtc59+최ㅇ9xy8e19QEtaNUyt1gprouyWnpOPqNJjL4gXMRMEpHYyLQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

 

to-top 버튼 만들기

<div id="to-top">
  <span class="material-symbols-outlined">arrow_upward</span>
</div>

 

  • 유일한 요소이므로 idto-top으로 부여한다.
  • Google Material Icons의 arrow_upward로 아이콘을 가져온다.

to-top 버튼 숨기기 / 보이기

const toTopEl = document.querySelector('#to-top');

window.addEventListener(
  'scroll',
  _.throttle(() => {
    if (window.scrollY > 500) {
      badgeEl.style.display = 'none';
      gsap.to(badgeEl, 0.6, {
        opacity: 0,
        display: 'none',
      });
      // 버튼 보이기
      gsap.to(toTopEl, 0.2, {
        x: 0,
      });
    } else {
      gsap.to(badgeEl, 0.6, {
        opacity: 1,
        display: 'block',
      });
      // 버튼 숨기기
      gsap.to(toTopEl, 0.2, {
        x: 100,
      });
    }
  }, 300),
);

 

  • #to-top 요소를 정의한다.
  • 이전의 배지와 동일하게 500px 이전으로 스크롤 되면 gsap.to() 메서드를 통해 x100으로 설정하여 오른쪽으로 숨기도록 한다.
  • 500px 이상으로 스크롤 되면 x를 0으로 설정하여 버튼이 제자리로오도록 한다.

 

페이지 상단 이동 구현하기

toTopEl.addEventListener('click', () => {
  gsap.to(window, 0.7, {
    scrollTo: 0,
  });
});

 

  • #to-top버튼을 클릭하면 gsap.top() 메서드를 통해 scrollTo 속성을 0으로 설정하여 페이지의 최상단으로 0.7초의 지연시간 동안 이동시킨다.

 

결과