🔖

【GSAP】GSAP Practice【#19 GSAP ScrollTrigger Sample2 Horizontal Scroll】

2025/01/27に公開

【#19 GSAP ScrollTrigger Sample2 Horizontal Scroll 2】

YouTube: https://youtu.be/cl8OJl555-E
https://youtu.be/cl8OJl555-E

今回はJSの部分を実装していきます。

HTMLの部分に誤りがありましたので、
まずはこちらの修正から行います。

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Gsap practice</title>
    <link
      href="https://cdn.jsdelivr.net/npm/remixicon@4.5.0/fonts/remixicon.css"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="css/main.css" />
  </head>
  <body>
    <div class="section-1">
      <div id="loading">Loading</div>
    </div>

    <div class="section-2">
      <div class="text-wrapper">
        <p class="text-overlay">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Amet
          quibusdam id fugiat cupiditate ea. Nobis voluptate eum enim
          reiciendis! Quam accusamus tempore ad provident doloribus libero
          incidunt tenetur, delectus omnis.
        </p>
        <p class="text">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Amet
          quibusdam id fugiat cupiditate ea. Nobis voluptate eum enim
          reiciendis! Quam accusamus tempore ad provident doloribus libero
          incidunt tenetur, delectus omnis.
        </p>
      </div>
    </div>

    <div class="section-3">
      <div class="container-wrapper wrapper-0">
        <div>
          <h2 class="box-title">Horizontal Scroll</h2>
        </div>
      </div>
      <div class="container-wrapper wrapper-1">
        <h2 class="box-title">Animation1</h2>
        <div class="box box-1"></div>
        <p class="box-text">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus
          eligendi possimus impedit facere consequatur ad eius error non
          corporis hic quibusdam, sint, enim soluta ullam rerum at id quod quo?
        </p>
      </div>
      <div class="container-wrapper wrapper-2">
        <h2 class="box-title">Animation2</h2>
        <div class="box box-2"></div>
        <p class="box-text">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus
          eligendi possimus impedit facere consequatur ad eius error non
          corporis hic quibusdam, sint, enim soluta ullam rerum at id quod quo?
        </p>
      </div>
      <div class="container-wrapper wrapper-3">
        <h2 class="box-title">Animation3</h2>
        <div class="box box-3"></div>
        <p class="box-text">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus
          eligendi possimus impedit facere consequatur ad eius error non
          corporis hic quibusdam, sint, enim soluta ullam rerum at id quod quo?
        </p>
      </div>
    </div>

    <script src="https://unpkg.com/lenis@1.1.16/dist/lenis.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
    <script src="js/main.js"></script>
  </body>
</html>
js/main.js
// use a script tag or an external JS file
document.addEventListener("DOMContentLoaded", (event) => {
  gsap.registerPlugin(ScrollTrigger);
  new App();
});

class App {
  constructor() {
    this._initialize();
    this._renderLenis();
  }

  _initialize() {
    this._createLenis();
    this._sec1Anime();
    this._sec2Anime();
    this._sec3Anime();
  }

  _createLenis() {
    this.lenis = new Lenis();
  }

  _renderLenis(time) {
    this.lenis.raf(time);
    requestAnimationFrame(this._renderLenis.bind(this));
  }

  _sec1Anime() {
    const loadingEl = document.querySelector("#loading");
    const loadingTexts = loadingEl.textContent.split("");
    let innerText = "";

    loadingTexts.forEach((text) => {
      innerText += `<span>${text}</span>`;
    });

    // console.log(loadingTexts);
    // console.log(innerText);

    loadingEl.innerHTML = innerText;

    const tl = gsap.timeline({ repeat: -1 });

    tl.to("#loading span", {
      duration: 1,
      y: -50,
      stagger: {
        each: 0.2,
        from: "left",
      },
    }).to("#loading span", {
      duration: 1,
      y: 0,
      stagger: {
        each: 0.2,
        from: "left",
      },
      ease: "bounce.out",
    });
  }

  _sec2Anime() {
    const textEl = document.querySelector(".text");
    const texts = textEl.textContent.split("");
    let innerText = "";
    texts.forEach((text) => {
      innerText += `<span>${text}</span>`;
    });

    textEl.innerHTML = innerText;

    // const tl1 = gsap.timeline({
    //   scrollTrigger: {
    //     trigger: ".section-2",
    //     scroller: "body",
    //     markers: true,
    //     start: "top top",
    //     end: "+=4000 100%",
    //     scrub: true,
    //     pin: true,
    //   },
    // });

    // tl1.from(".text span", {
    //   opacity: 0,
    //   stagger: 0.5,
    // });
  }
  _sec3Anime() {
    let wrappers = gsap.utils.toArray(".container-wrapper");

    gsap.set(".section-3", {
      width: wrappers.length * 100 + "vw",
    });

    let scrollTween = gsap.to(wrappers, {
      xPercent: -100 * (wrappers.length - 1),
      ease: "none",
      scrollTrigger: {
        trigger: ".section-3",
        pin: true,
        scrub: 0.1,
        start: "top top",
        end: "+=3000 100%",
        markers: true,
        snap: 1 / (wrappers.length - 1),
      },
    });

    document.querySelectorAll(".container-wrapper").forEach((el) => {
      gsap.set(el.querySelector(".box"), {
        scale: 6,
        opacity: 0,
        borderRadius: "50%",
      });
      gsap.set(el.querySelector(".box-title"), {
        scale: 3,
        opacity: 0,
      });
      gsap.set(el.querySelector(".box-text"), {
        scale: 3,
        opacity: 0,
      });

      gsap.to(el.querySelector(".box"), {
        borderRadius: "5px",
        scale: 2,
        opacity: 1,
        scrollTrigger: {
          containerAnimation: scrollTween,
          trigger: el.querySelector(".box"),
          start: "top center",
          end: "center center",
          scrub: 0.5,
          markers: true,
        },
      });

      gsap.to(el.querySelector(".box-title"), {
        scale: 1.5,
        opacity: 1,
        scrollTrigger: {
          containerAnimation: scrollTween,
          trigger: el.querySelector(".box-title"),
          start: "top center",
          end: "center center",
          scrub: 0.5,
        },
      });

      gsap.to(el.querySelector(".box-text"), {
        scale: 1,
        opacity: 1,
        scrollTrigger: {
          containerAnimation: scrollTween,
          trigger: el.querySelector(".box-text"),
          start: "top center",
          end: "center center",
          scrub: 0.5,
        },
      });
    });
  }
}

Discussion