旧ブログ(ISSEN)から移行しました

【ScrollTrigger】forEach文を使用した繰り返し処理とスクロール量に合わせたアニメーション

【ScrollTrigger】forEach文を使用した繰り返し処理とスクロール量に合わせたアニメーション

杉田侑祐
杉田侑祐8分で読めます

はじめに

この記事の概要

こんにちは、株式会社TOKOSエンジニアのスギタです!

今回は、GreenSock社が開発したGreenSock Animation Platform(GSAP)のScrollTriggerを使いスクロールアニメーションを行ってみようと思います。
またGSAPでの繰り返し処理とスクロール量に合わせたアニメーションも合わせて実装していきたいと思います。
また基本的なGSAPの使い方やScrollTriggerの使い方がわからないかたは下記の記事を参考にしてください!

【初学者向け】GSAPでテキストアニメーションをやってみた!!

この記事では、GreenSock社が開発したGreenSock Animation Platform(GSAP)を使いテキストアニメーションを学ぶことができます。 基本的な使い方から学び、実際にテキストアニメーションを実装する方法を紹介しています。

【ScrollTrigger】スクロールするとふわっと浮き出るスクロールアニメーション

GSAPのScrollTriggerを使って、スクロールすると要素がふわっと浮き出るアニメーションを実装する方法を解説します。

対象読者

  • Web制作でアニメーションの実装をしたい方

今回の完成予定

今回はテキストに対して、以前やったスクロールするとふわっと浮き出るアニメーションに加え、画像にはスクロール量に対して画像の位置が変わるアニメーションを行っていきます。

GSAPとScrollTriggerの導入

GSAPを利用するには、オフィシャルサイトからダウンロードするか、CDNでも提供されているので公式HPを参照してください。
今回はCDNを利用していきたいと思います。

Installation | GSAP | Docs & Learning

GSAP is "framework agnostic", this means it can be used in React, Webflow, Wordpress, or any other JS/Web frameworks. The core GSAP file and all the plugins are just Javascript files.

greensock.com

コードの紹介

では1つずつ分解して紹介していきます。

レイアウトを整える

HTML
<body>
  <div class="fv"></div>
  <div class="layout">
    <div class="content">
      <div class="wrapper js-scroll">
        <img src="./img/image1.jpg" alt="山" class="image " />
      </div>
      <p class="text js-scroll-text">
        私も生涯人知れずその観察者というのの時を入ったん。現に当時に講演学はつるつるこうした附随なけれありでもをしてくれなかっをは注意したたて、そうとはついたないなです。徳義にぶらです方はまあ前にけっしてあるたです。おもに岡田さんで相当主義そう話が借りた亡骸この壇これか随行がというご話たたましだろから、同じ昔は私か珍個性をあるて、嘉納さんののを取消の私を単にお注意とならてそこ空腹にご観念をあるように同時におお話をするありたので、ただいまはたして記憶が当てべきでいですのに上げだっん。またするとお教授でもっのはそれだけ危険と云うないが、この徳義心へもなりだがという中腰をさておりまします。
      </p>
    </div>
    <div class="content">
      <p class="text js-scroll-text">
        私も生涯人知れずその観察者というのの時を入ったん。現に当時に講演学はつるつるこうした附随なけれありでもをしてくれなかっをは注意したたて、そうとはついたないなです。徳義にぶらです方はまあ前にけっしてあるたです。おもに岡田さんで相当主義そう話が借りた亡骸この壇これか随行がというご話たたましだろから、同じ昔は私か珍個性をあるて、嘉納さんののを取消の私を単にお注意とならてそこ空腹にご観念をあるように同時におお話をするありたので、ただいまはたして記憶が当てべきでいですのに上げだっん。またするとお教授でもっのはそれだけ危険と云うないが、この徳義心へもなりだがという中腰をさておりまします。
      </p>
      <div class="wrapper js-scroll">
        <img src="./img/image2.jpg" alt="山" class="image" />
      </div>
    </div>
    <div class="content">
      <div class="wrapper js-scroll">
        <img src="./img/image3.jpg" alt="山" class="image" />
      </div>
      <p class="text js-scroll-text">
        私も生涯人知れずその観察者というのの時を入ったん。現に当時に講演学はつるつるこうした附随なけれありでもをしてくれなかっをは注意したたて、そうとはついたないなです。徳義にぶらです方はまあ前にけっしてあるたです。おもに岡田さんで相当主義そう話が借りた亡骸この壇これか随行がというご話たたましだろから、同じ昔は私か珍個性をあるて、嘉納さんののを取消の私を単にお注意とならてそこ空腹にご観念をあるように同時におお話をするありたので、ただいまはたして記憶が当てべきでいですのに上げだっん。またするとお教授でもっのはそれだけ危険と云うないが、この徳義心へもなりだがという中腰をさておりまします。
      </p>
    </div>
  </div>
</body>
CSS
/* resetcssは省略 */
body {
  background-color: black;
}
 
.fv {
  width: 100vw;
  height: 100vh;
}
 
.layout {
  width: fit-content;
  margin: auto;
  padding: 200px 16px;
}
 
.content {
  display: flex;
  align-items: center;
  gap: 0px 40px;
  margin-top: 120px;
}
 
.wrapper {
  max-width: 600px;
}
 
.image {
  width: 100%;
  height: auto;
}
 
.text {
  max-width: 600px;
  color: #fff;
}

あまり説明することはありません。
お好きなフォントとレイアウトにしちゃってください!

前回の確認

ではまず以前紹介したような、スクロールの位置に対して、フワッと浮き出てくるアニメーションをテキストに実装していきたいと思います。
まずは前回のコード確認をします。

JavaScript
gsap.fromTo(
  ".hoge1",
  { y: 20, autoAlpha: 0 },
  {
    y: 0,
    autoAlpha: 1,
    scrollTrigger: {
      trigger: ".hoge", //triggerさせる要素をアニメーションが始まる直前の要素を指定していた
      start: "bottom top",
    },
  },
)
gsap.fromTo(
  ".hoge2",
  { y: 20, autoAlpha: 0 },
  {
    y: 0,
    autoAlpha: 1,
    scrollTrigger: {
      trigger: ".hoge1", //triggerさせる要素をアニメーションが始まる直前の要素を指定していた
      start: "bottom top",
    },
  },
)

前回はScrollTrigger内の記述でtriggerに直前の要素を指定していたと思います。
それでは、アニメーションをかけたい要素の数分の記述が必要になってしまいます。
細かく1つずつ指定できるのは良いかもしれませんが、やはり記述量が多くなってしまいます。
やはり同じアニメーションであれば、繰り返し処理などを使って処理するべきです。

Utility Methodsの使用

では繰り返し処理をしようとした場合は要素を配列に格納する必要があります。
そのためにGSAPではいろいろなことができるUtility Methodsという様々な便利なメソッドを用意してくれています。
興味のある方は下記を参照してみてください。

Utility Methods | GSAP | Docs &amp; Learning

---

greensock.com

今回Utility Methodsの中のtoArray()メソッドを使用していきます。
このメソッドはセレクターを用いて要素を取得し、配列に格納してくれます。

例)toArray(".class") ==> [element, element2]
このように要素を指定し配列に格納していってくれます。
ではこのことを踏まえクラス名.js-scroll-textを配列に入れていきたいと思います。
gsap.utils.toArray(".hoge");で配列の生成ができます。

JavaScript
const texts = gsap.utils.toArray(".js-scroll-text")

これでtextsという配列を生成できました。
ではこれに対してforEach文で繰り返し処理を行っていきたいと思います。

JavaScript
const texts = gsap.utils.toArray(".js-scroll-text")
texts.forEach((text) => {
  gsap.fromTo(
    text,
    {
      y: 40,
      autoAlpha: 0,
    },
    {
      y: 0,
      autoAlpha: 1,
      scrollTrigger: {
        trigger: text, //アニメーションが始まるトリガーとなる要素
        start: "top-=100px center", //アニメーションが始まる位置
      },
    },
  )
})

これでテキストに対しアニメーションの実装の完了です。
ScrollTrigger内の記述でトリガーとなる要素は、前回はアニメーションが始まる直前の要素にしていましたが、今回はアニメーションの対象の要素にしています。
そのほうが直前の要素名に依存せず、使いまわしがより柔軟にできると思います。
これでテキストに対するアニメーションは完了です。

スクロール量に合わせたアニメーションの実装

それでは次にスクロール量に合わせたアニメーションの実装です。
では早速紹介していきます。

JavaScript
const images = gsap.utils.toArray(".js-scroll")
images.forEach((image) => {
  gsap.to(image, {
    y: -100,
    scrollTrigger: {
      trigger: image,
      start: "top center",
      end: "bottom center",
      scrub: 1,
    },
  })
})

今回も先程紹介した、繰り返し処理をもとに実装していきます。
今回はto()メソッドで指定しています。
ScrollTrigger内の記述でいつもと違う箇所があります。
end: "bottom center"scrub: 1です。
これが、スクロール量に対しての記述になります。
分かりづらいと思いますのでmarkers: trueにして確認していきます。

JavaScript
const images = gsap.utils.toArray(".js-scroll")
images.forEach((image) => {
  gsap.to(image, {
    y: -100,
    scrollTrigger: {
      trigger: image,
      start: "top center",
      end: "bottom center",
      scrub: 1,
      markers: true,
    },
  })
})

startendでアニメーションの開始地点と終了地点を指定し、それに対しscrubでスクロール量に対してアニメーションしてねという感じです。
scrubはスクロールに対しての遅延する秒数を指定します。
これでスクロールごとに1秒間アニメーションを実行させることができるようになります。

さいごに

今回はスクロールアニメーションの繰り返し処理とスクロール量に対してのアニメーションの実装を行いました。
今回紹介したUtility MethodstoArray()メソッド以外にも使えそうなメソッドがありましたので、また別の機会に使用してみようと思います。
またスクロール量に対してのアニメーションも最近のモダンなHP等ではよく見かけるので、使用できるようになると表現の幅も広がるなと感じました。

この記事を書いた人

杉田侑祐
杉田侑祐

TOKOSのフロントエンドエンジニア兼UI/UXデザイナー。このブログではフロントエンドメインで投稿しています。HIPHOPとゲームが好きです✌️