오늘은 GSAP(ScrollTrigger)와 Lenis 라이브러리를 써서 스크롤에 따라 반응하는 애니메이션을 만들어보았다

 

사용 라이브러리 (플러그인)

- GSAP

- ScrollTrigger(GSAP에서 제공하는 또다른 플러긘)

- Lenis (부드러운 스크롤 제공)

 

완성작

 

HTML 구조

<section>
  <!-- 이미지 영역 -->
  <div class='img_area'>
    <img src='https://images.unsplash.com/photo-1607798748738-b15c40d33d57?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'>
    <img src='https://images.unsplash.com/photo-1624377632657-3902bfd35958?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'>
    <img src='https://images.unsplash.com/photo-1607706189992-eae578626c86?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'>
  </div>
  
  <!-- 텍스트 영역 -->
  <div class='txt_area'>
    <ul class='txt_container'>
      <li>GSAP</li>
      <li> ScrollTrigger</li>
      <li>SmoothScroll</li>
    </ul>
  </div>
</section>

 

이미지 영역과 텍스트 영역을 나눠준다. 

 

CSS

section {width: 100%; overflow-x: hidden;}

.img_area {width: 100%;}
.img_area img {width: 100%; height: 100vh; object-fit: cover; position: absolute; left: 0; top: 0;}

.txt_area {position: relative; }
.txt_area .txt_container {text-align: center; color: #fff; font-size: 3rem;}
.txt_area .txt_container li {height: 100vh; display: flex; align-items: center; justify-content: center;}

 

여기서 중요한 점은 img_area에 있는 이미지들을 absolute로 주어 3장 다 고정시켜주어야 한다.

 

텍스트는 높이를 100vh로 잡아놓은 뒤 화면 가운데에 배치하기 위해 flex,와 content, items요소들을 center로 잡는다.

txt_area에 position: relative를 준 이유는 img_area를 고정시켰기 때문.

 

스크립트 주소 연동

<script src='https://unpkg.com/gsap@3/dist/gsap.min.js'></script>
<script src='https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js'></script>
<script src='https://unpkg.com/lenis@1.1.14/dist/lenis.min.js'></script>

 

사용할 스크립트 주소를 적어 연동한다.

순서대로

 

GSAP -> ScrollTrigger -> Lenis

 

스크립트 작성

// Lenis 초기화
const lenis = new Lenis({
  duration: 1.2,
  easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
  smooth: true,
});

const raf = (time) => {
  lenis.raf(time);
  requestAnimationFrame(raf);
};
requestAnimationFrame(raf);

 

일단 부드러운 스크롤 먼저 적용 시켜보자.

 

Lenis 초기화

  • duration: 스크롤 애니메이션의 지속 시간을 설정. 여기서는 1.2초로 설정
  • easing: 스크롤 애니메이션의 속도 곡선을 정의하는 함수. 여기서 사용된 함수는 타임(t) 값을 입력받아 0에서 1까지의 값을 출력하는데, 이 방식은 부드러운 시작과 끝을 만들기 위해 비선형적인 애니메이션 효과를 제공.
  • smooth: 속성이 true 설정되면 부드러운 스크롤 효과를 활성화.

애니메이션 프레임 요청

  • raf: 이 함수는 requestAnimationFrame을 사용하여 Lenis의 스크롤 메커니즘을 매 프레임마다 업데이트함. time 매개변수는 현재 시간의 타임스탬프를 나타냄.
  • lenis.raf(time): 이 호출은 Lenis의 내부 애니메이션 로직을 업데이트.
  • requestAnimationFrame(raf): 함수는 다음 프레임에 raf 함수를 다시 호출하도록 요청. 이렇게 하여 부드러운 애니메이션 효과를 지속적으로 유지한다.
// 이미지 초기 설정
const images = document.querySelectorAll('.img_area img'); // querySelectorAll로 모든 이미지 가져와서 변수에 저장
gsap.set(images, { zIndex: 0, opacity: 0 }); // 모든 이미지의 z-index값과 opacity를 0으로 설정
gsap.set(images[0], { opacity: 1, zIndex: 1 }); // 첫 번째 이미지만 보이게 설정

// GSAP ScrollTrigger 설정
gsap.registerPlugin(ScrollTrigger);
const timeline = gsap.timeline({
  scrollTrigger: {
    trigger: ".img_area",
    start: "top top",
    end: "bottom bottom",
    endTrigger: '.txt_container',
    scrub: true,
    pin: true,
    pinSpacing: false,
    onEnter: () => {
      gsap.to(images[0], { opacity: 1, zIndex: 1, duration: 0.7 }); // 페이지 로드 시 첫 번째 이미지 보이기
    }
  },
});

// 각 텍스트 항목에 대한 ScrollTrigger 생성
gsap.utils.toArray('.txt_container li').forEach((li, index) => {
    ScrollTrigger.create({
        trigger: li,
        start: 'top 80%',
        end: 'bottom top',
        onEnter: () => {
            gsap.to(images[index], { opacity: 1, zIndex: 1, duration: 0.7 });
        },
        onLeaveBack: () => {
            gsap.to(images[index], { opacity: 0, zIndex: 0, duration: 0.7 });
        },
        markers: true,
    });
});

 

맨 처음 이미지 초기 설정을 해야한다.

 

이미지 초기 설정

  • 이미지 선택: .img_area 클래스 아래의 모든 이미지 요소를 선택하여 images 변수에 저장.
  • 초기 스타일 설정: 모든 이미지의 zIndex와 opacity를 0으로 설정하여 처음에는 보이지 않도록 한다.
  • 번째 이미지 설정: 번째 이미지만 opacity 1 설정하여 보이도록 하고, zIndex 1 설정하여 다른 이미지보다 위에 표시되도록 한다.

이미지 고정하는 ScrollTrigger Pin 효과 생성

  • ScrollTrigger 등록:  GSAP의 ScrollTrigger 플러그인을 등록함.
  • 타임라인 생성: GSAP의 타임라인을 생성하고, 스크롤과 관련된 애니메이션을 설정함. 

옵션 부가 설명 보기

더보기
  • trigger: 스크롤을 감지할 요소입니다. 여기서는 .img_area를 지정했습니다.
  • start: 스크롤의 시작 위치를 정의합니다. 여기서는 .img_area의 최상단이 뷰포트의 최상단에 도달할 때 시작합니다.
  • end: 스크롤의 끝 위치를 정의합니다. 여기서는 .img_area의 하단이 뷰포트의 하단에 도달할 때 종료합니다.
  • endTrigger: 끝 위치를 결정하는 다른 요소를 지정합니다. 여기서는 .txt_container를 사용합니다.
  • scrub: true로 설정하면 스크롤에 따라 애니메이션의 진행이 동기화됩니다.
  • pin: true로 설정하면 해당 요소를 고정(pinning)하여 스크롤 중에도 화면에 고정됩니다.
  • pinSpacing: false로 설정하면 핀 고정 시 추가 공간을 차지하지 않게 합니다.
  • onEnter: 스크롤이 시작될 때 첫 번째 이미지를 보이도록 애니메이션을 설정합니다.

 

  텍스트 항목에 대한 ScrollTrigger 생성

  • 텍스트 항목 선택: .txt_container 내의 모든 <li> 요소를 배열로 변환하여 각각의 텍스트 항목에 대해 반복.
  • ScrollTrigger 생성: 텍스트 항목에 대해 ScrollTrigger 생성하여 스크롤과 관련된 애니메이션을 설정.

옵션 부가 설명 보기

더보기
  • trigger: 현재 <li> 요소를 스크롤 트리거로 설정합니다.
  • start: 해당 요소의 최상단이 뷰포트의 80% 지점에 도달할 때 애니메이션이 시작됩니다.
  • end: 해당 요소의 하단이 뷰포트의 최상단에 도달할 때 애니메이션이 종료됩니다.
  • onEnter: 해당 텍스트 항목이 뷰포트에 들어오면 해당 인덱스의 이미지를 보이도록 애니메이션을 설정합니다.
  • onLeaveBack: 해당 텍스트 항목이 뷰포트를 벗어나면 해당 인덱스의 이미지를 숨기도록 애니메이션을 설정합니다.
  • markers: true 설정하면 디버깅을 위해 스크롤 트리거의 시작과 지점을 화면에 표시합니다.

 

728x90
반응형
다쭐◠‿◠