[GSAP] 예제 - Pin과 timeline으로 요소 등장

Lpla

·

2021. 6. 18. 23:34

반응형

 

GSAP ScrollTrigger의 Pintimeline을 사용하여 효과를 구현하고자 한다.

어떤 지점에 도달하면 스크롤 하더라도 배경은 유지된 채, 수평 방향에서 요소가 등장하는 효과다.

배경을 유지하는 것은 pin, 요소가 등장하는 것은 timeline으로 구현할 수 있다.

 

 

최종 결과물

 

1. 준비

<!DOCTYPE html>
<html lang="ko">
<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">
  <title>Document</title>
  <link rel="stylesheet" href="./style.css">
  <script src="./js/gsap.min.js"></script>
  <script src="./js/ScrollTrigger.min.js"></script>
</head>

<body>


  <script src="./js/script.js"></script>
</body>

</html>

head에 GSAP와 ScrollTrigger를 추가하고 하단에 자바스크립트 외부 파일을 추가했다.

 

 

2. HTML, CSS

<section id="section1">
  <p>section1</p>
</section>
<section id="section2">
  <p>section2</p>
  <div class="box_wrapper">
    <div class="box box1 horizon_box">
      <h1>1</h1>
    </div>
    <div class="box box2 horizon_box">
      <h1>2</h1>
    </div>
    <div class="box box3 horizon_box">
      <h1>3</h1>
    </div>
  </div>
</section>
<section id="section3">
  <p>section3</p>
</section>
<section id="section4">
  <p>section4</p>
</section>

body에 section 요소 4개를 추가했다.

여기서 화면이 고정될 요소는 section2다.

즉 pin을 section2에 부여할 것이다.

그리고 pin이 유지되는 동안 서서히 나타나게 될 요소들은 box다.

 

 

 

 

* { margin: 0; }
body { margin: 0; }
section { position: relative; width: 100%; height: 100vh; }
#section1 { background: yellowgreen; }
#section2 { background: goldenrod; overflow: hidden; }
#section3 { background: indianred; }
#section4 { background: paleturquoise; }
.horizon_box { position: absolute; top: 0; left: 100%; }
.box { display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; }
.box h1 { font-size: 50px; text-align: center; }
.box2 { background: crimson; }
.box3 { background: darkorchid; }

css는 특별히 설명할 게 없다.

각 section을 화면에 가득 채울 수 있도록 크기를 조절하고 배경색을 추가했다.

그리고 box들은 left: 100%; 를 사용하여 화면에 보이지 않게 우측 끝으로 밀어 버렸다.

 

여기까지 작업하고 페이지를 확인해보면 아래와 같다.

 

 

 

3. JavaScript

이제 페이지를 스크롤 했을 때, section2에서 화면이 먼저 고정되고, box가 순서대로 등장한 다음, 다시 수직으로 세션이 넘어가도록 한다.

 

 

 

var $sections = document.querySelectorAll(".horizon_box");
var tl = gsap.timeline({
  scrollTrigger: {
    trigger: "#section2",
    pin: true,
    scrub: 0.3,
    start: "top top",
    end: "+=3000"
  }
});
tl.to($sections, {xPercent: -100, duration:2, ease: "none", stagger:3})
  .to({},{duration:1});

 

프로퍼티나 메서드에 대한 설명은 지난 시간에 충분히 해서 생략하고 결과만 말해 section2에 높이 3000px의 pin을 걸었다.

그리고 pin이 유지되는 동안 timeline()으로 box들이 x축으로 -100% 만큼 이동하도록 했다.

 

 

마지막에 duration: 1을 건 이유는 이게 없으면 마지막 box3이 끝나자마자 바로 세션이 내려가기 때문에 추가했다.

 

 

 

하지만 이 결과물은 내가 최종적으로 원하는 효과를 가지고 있진 않다.

그렇지만 여기서 약간만 응용하면 되기 때문에 여기까지 이해했다면 최종 결과물을 만드는 것은 크게 어렵지 않다.

 

 

 

4. box 수정

먼저 화면을 가득 채우도록 세팅한 box의 사이즈를 조절하고 position: absolute;로 정렬시킨 위 box와 달리 display: flex;로 한 줄로 정렬 시킨다. 

 

 

 

 

* { margin: 0; }
body { margin: 0; }
section { position: relative; width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; flex-direction: column; }
section p { font-size: 40px; margin-bottom: 50px; }
#section1 { background: yellowgreen; }
#section2 { background: goldenrod; overflow: hidden; }
#section3 { background: indianred; }
#section4 { background: paleturquoise; }
.box h1 { font-size: 50px; text-align: centerspa; }
.box1 { background: darkslategray; }
.box2 { background: crimson; }
.box3 { background: darkorchid; }
.box_wrapper { display: flex; justify-content: space-around; width: 100%; }
.box { width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; opacity: 1; }

 

이번에는 timeline().to 대신에 timeline().from을 사용했다.

 

 

to를 쓰지 않은 이유는 그저 from이 더 쉬워 보여서 그런 것이고 to를 써서 위치를 맞춰도 된다.

 

var $sections = document.querySelectorAll(".horizon_box");
var tl = gsap.timeline({
  scrollTrigger: {
    trigger: "#section2",
    pin: true,
    scrub: 0.3,
    start: "top top",
    end: "+=300%",
  }
});
tl.from($sections, {x: '300%', autoAlpha: 0, duration:2, ease: "none", stagger:3})
  .to($sections, {duration: 3});

 

 

 

약간의 css와 자바스크립트 메서드를 사용하여 내가 원하는 결과물을 얻었다.

 

반응형