본문 바로가기
Tutorial/GSAP

12. GSAP Parallax Effect : 가로 효과

by @webstoryboy 2023. 6. 20.
Tutorial/webd

GSAP 패럴랙스 이펙트 : 가로 효과

by @webs 2023. 06. 01.
12
GSAP Parallax Effect : 가로 효과
난이도 중간
소스 다운로드
완성 화면 소스 보기 유튜브

소개

안녕하세요! 웹스토리보이입니다. 패럴랠스의 하이라이트 가로 효과입니다. 저도 이 효과 때문에 GSAP를 사용했는데요! GSAP를 이용하면 쉽고 간편하게 효과를 줄 수 있습니다. 물론 처음에는 이해하는 과정이 필요합니다. 필수 속성 값을 알고 있어야, 내가 원하는 장소에서 스크롤 효과를 제대로 줄 수 있습니다. 보통은 스크롤 이팩트가 세로로 작동하지만, 가로로 작동하는 사이트들도 많이 볼 수 있기 때문에 이번에는 가로로 한번 작업해 보겠습니다. 그럼 시작해볼까요? 🤭

1. 기본 구조 만들기

1-1. 준비하기

GSAP를 배우는 시간이기 때문에 HTML/CSS 코딩은 생략하겠습니다. 기본 코딩은 복사해서 사용하겠습니다. 우선 웹폰트를 설정하고 GSAP에서 필요한 파일을 미리 셋팅해 놓겠습니다. GSAP는 자주 업데이트가 되기 때문에 제일 최선 버전을 사용하는게 좋습니다.

<!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>GSAP Scroll Effect</title>

    <!-- 웹폰트 설정 -->
    <link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Lato:wght@100&display=swap" rel="stylesheet">
</head>
<body>

    <!-- GSAP 라이브러리 설정 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
</body>
</html>

1-2. 기본 셋팅하기

소스는 그대로 복사해서 사용하겠습니다.

<!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>GSAP Scroll Effect</title>

    <link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Lato:wght@100&display=swap" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        a {
            color: #fff;
            text-decoration: none;
        }
        body {
            color: #fff;
            font-family: "NexonLv1Gothic";
            font-weight: 300;
            background-color: #333;
        }
        #parallax__title {
            position: fixed;
            left: 20px;
            top: 20px;
            z-index: 1000;
        }
        #parallax__title h1 {
            font-size: 30px;
            border-bottom: 1px dashed #fff;
            margin-bottom: 10px;
            padding-bottom: 5px;
            font-weight: 400;
            display: inline-block;
        }
        #parallax__title p {
            font-size: 16px;
        }
        #parallax__title ul {
            margin-top: 10px;
        }
        #parallax__title li {
            display: inline;
        }
        #parallax__title li a {
            width: 20px; 
            height: 20px;
            border-radius: 50%;
            border: 1px dashed #fff;
            display: inline-block;
            text-align: center;
            line-height: 20px;
            font-size: 12px;
        }
        #parallax__title li.active a {
            background: #fff;
            color: #000;
        }

        /* parallax__cont */
        .parallax__item {
            width: 100%;
            height: 100vh;
            position: relative;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .parallax__item__num {
            font-size: 5vw;
            position: absolute;
            right: 20px;
            bottom: 20px;
            font-family: "Lato";
            font-weight: 100;
            z-index: 100;
        }
        .parallax__item__imgWrap {
            width: 30%;
            padding-bottom: 18%;
            position: relative;
            overflow: hidden;
            border-radius: 10px;
        }
        .parallax__item__img {
            position: absolute;
            left: -5%; 
            top: -5%;
            width: 110%;
            height: 110%;
            background-repeat: no-repeat;
            background-position: center center;
            background-size: cover;
            filter: saturate(0%);
            transition: all 1s;
        }
        .parallax__item__img:hover {
            filter: saturate(100%);
            transform: scale(1.025);
        }
        #section1 .parallax__item__img {
            background-image: url(assets/img/images01@2.jpg);
        }
        #section2 .parallax__item__img {
            background-image: url(assets/img/images02@2.jpg);
        }
        #section3 .parallax__item__img {
            background-image: url(assets/img/images03@2.jpg);
        }
        #section4 .parallax__item__img {
            background-image: url(assets/img/images04@2.jpg);
        }
        #section5 .parallax__item__img {
            background-image: url(assets/img/images05@2.jpg);
        }
        #section6 .parallax__item__img {
            background-image: url(assets/img/images06@2.jpg);
        }
        #section7 .parallax__item__img {
            background-image: url(assets/img/images07@2.jpg);
        }
        #section8 .parallax__item__img {
            background-image: url(assets/img/images08@2.jpg);
        }
        #section9 .parallax__item__img {
            background-image: url(assets/img/images09@2.jpg);
        }
        #section1, #section3, #section5, #section7, #section9 {
            background-color: #111;
        }
    </style>
</head>
<body>
    <header id="parallax__title">
        <h1>GSAP Parallax Effect12</h1>
        <p>GSAP scrollTrigger - 가로 효과</p>
        <ul>
            <li><a href="gsap01.html">1</a></li>
            <li><a href="gsap02.html">2</a></li>
            <li><a href="gsap03.html">3</a></li>
            <li><a href="gsap04.html">4</a></li>
            <li><a href="gsap05.html">5</a></li>
            <li><a href="gsap06.html">6</a></li>
            <li><a href="gsap07.html">7</a></li>
            <li><a href="gsap08.html">8</a></li>
            <li><a href="gsap09.html">9</a></li>
            <li><a href="gsap10.html">10</a></li>
            <li><a href="gsap11.html">11</a></li>
            <li class="active"><a href="gsap12.html">12</a></li>
            <li><a href="gsap13.html">13</a></li>
            <li><a href="gsap14.html">14</a></li>
            <li><a href="gsap15.html">15</a></li>
        </ul>
    </header>
    <!-- //parallax__title  -->

    <main id="parallax__cont">
        <section id="section1" class="parallax__item">
            <span class="parallax__item__num">01</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section1 -->

        <section id="section2" class="parallax__item">
            <span class="parallax__item__num">02</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section2 -->

        <section id="section3" class="parallax__item">
            <span class="parallax__item__num">03</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section3 -->

        <section id="section4" class="parallax__item">
            <span class="parallax__item__num">04</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section4 -->

        <section id="section5" class="parallax__item">
            <span class="parallax__item__num">05</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section5 -->

        <section id="section6" class="parallax__item">
            <span class="parallax__item__num">06</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section6 -->

        <section id="section7" class="parallax__item">
            <span class="parallax__item__num">07</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section7 -->

        <section id="section8" class="parallax__item">
            <span class="parallax__item__num">08</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section8 -->

        <section id="section9" class="parallax__item">
            <span class="parallax__item__num">09</span>
            <figure class="parallax__item__imgWrap">
                <div class="parallax__item__img"></div>
            </figure>
        </section>
        <!-- //section9 -->
    </main>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
    <script>
        
    </script>
</body>
</html>

2. 스크립트 작업하기

2-1. 작업하기

우선 가로로 작업하기 위해서는 레이아웃부터 가로로 셋팅이 되어야 합니다. 다음과 같이 전체 섹션이 9개이기 때문에 900%로 설정했습니다. 높이는 100vh를 사용하고, display: flex;를 이용하여 가로로 정렬했습니다. 이렇게 기본이 되어 있는 상태에서 스크립트 작업을 해야 합니다.

#parallax__cont {
    overscroll-behavior: none;
    width: 900%;
    height: 100vh;
    display: flex;
    flex-wrap: nowrap;
}

먼저, gsap.utils.toArray(".parallax__item")은 CSS 클래스가 "parallax__item"인 요소들을 선택하여 배열로 반환하는 코드입니다. 즉, .parallax__item 클래스를 가진 모든 요소를 선택하고, 이를 sections 변수에 배열로 저장합니다. 다음으로, gsap.to() 메서드를 사용하여 선택한 요소들에 대한 애니메이션을 정의합니다. 이 경우 sections 배열에 포함된 모든 요소들을 대상으로 애니메이션을 적용하게 됩니다.

xPercent: -100 * (sections.length - 1)은 요소들을 가로 축으로 이동시키는 애니메이션 속성입니다. xPercent는 요소의 가로 위치를 퍼센트로 지정하는 것을 의미하며, -100 * (sections.length - 1)는 마지막 요소를 제외한 모든 요소들을 왼쪽으로 100%만큼 이동시킵니다. 이렇게 하면 요소들이 수평으로 배치된 것처럼 보이는 효과를 얻을 수 있습니다. ease: "none"은 애니메이션의 움직임을 부드럽게 하는 이징(easing) 효과를 적용하지 않겠다는 의미입니다.

scrollTrigger 객체는 스크롤 이벤트와 관련된 설정을 정의합니다. trigger 속성은 #parallax__cont는 스크롤 트리거로 사용될 요소를 지정합니다. 여기서는 #parallax__cont라는 ID를 가진 요소를 선택했습니다. pin: true 속성은 스크롤 트리거 요소를 고정시키는 옵션입니다. 즉, 트리거 요소가 스크롤되면서 다른 요소들이 지나가는 것처럼 보이게 됩니다. scrub: 1속성은 트리거 요소가 스크롤되는 동안 애니메이션을 부드럽게 진행하기 위한 옵션입니다. snap: 1 / (sections.length - 1) 속성은 스크롤 위치를 요소들의 위치에 스냅하는 옵션입니다. 1 / (sections.length - 1)은 각 요소 사이의 스냅 간격을 설정합니다. end: "+=7000"은 애니메이션이 끝나는 시점을 지정하는 옵션입니다. +=7000은 현재 스크롤 위치에서 7000px만큼 스크롤되면 애니메이션이 종료됨을 의미합니다.

let sections = gsap.utils.toArray(".parallax__item");

gsap.to(sections, {
    xPercent: -100 * (sections.length - 1),
    ease: "none",
    scrollTrigger: {
        trigger: "#parallax__cont",
        pin: true,
        scrub: 1,
        snap: 1 / (sections.length - 1),
        end: "+=7000",
        // end: document.querySelector("#parallax__cont").offsetWidth,
    }
});

3. 마무리

가로 효과도 완성을 하였습니다. 가로 효과만 있다면 조금 단순할 수도 있기 때문에 여기에서 조금 더 퀄리티를 높일려면, 가로와 세로를 혼합해서 사용하면 조금더 그럴듯한 사이트를 만들 수 있습니다. 그 부분은 다음 섹션에서 배우겠습니다. 그전에 가로 모드는 완벽하게 이해해야 겠죠^^ 그럼 오늘도 수고하셨습니다. 😷


예제 목록

댓글