Web活のロゴ

Web制作Output&初心者のための徹底ガイド

【Gsap】スクロールアニメーション

2024.03.11
はじめに
概要

この一連のコードは、ウェブページの構造、スタイル、および動的なインタラクションを定義するために使用されます。HTMLでページの基本的な骨格を作成し、CSS(Sassを含む)で視覚的スタイルを適用し、GSAPとScrollTriggerを使用してスクロールに基づいたアニメーションを実装しています。Gsapで魅力のあるアニメーションを実装しましょう

スポンサーリンク
※本記事の情報は執筆時点のものであり、閲覧時点では変更されている可能性があります。また、ご利用の環境によっては、本記事の内容が正常に動作しないことがあります。最新の情報については、公式サイトなどでご確認ください。

実装内容

See the PenGsap-animationby kimura souichi (@kimura-souichi) onCodePen.

タイトル

テキストテキストテキストテキスト

タイトル

テキストテキストテキストテキスト

タイトル

テキストテキストテキストテキスト

タイトル

テキストテキストテキストテキスト

タイトル

テキストテキストテキストテキスト

コード

GitHubからもコードをダウンロードできます。
以下に個別のコードと解説を記述しています。

HTML

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/destyle.css@1.0.15/destyle.css" />
  <link rel="stylesheet" href="./dist/css/style.min.css">
  <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="/gsap.js" defer></script>
</head>

<body>
  <div id="global-container">
    <div id="container">
      <header class="header js-cont-1">header</header>
      <main>
        <div id="main-container" class="wrap">
          <div class="content-skew">
            <div class="content-skew__inner flex-column">
              <div class="content-skew__wrap js-cont-2">
                <div class="content-skew__box">
                  <div class="content-skew__cover js-10-1"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__txt">
                    <div class="content-skew__txt-inner js-10-2">
                      <h2>タイトル</h1>
                        <p>テキストテキストテキストテキスト</p>
                    </div>
                  </div>
                  <img class="js-10-3" src="https://picsum.photos/1000?random=3" alt="">
                </div>
              </div>
              <div class="content-skew__wrap js-cont-3">
                <div class="content-skew__box">
                  <div class="content-skew__cover js-11-1"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__txt">
                    <div class="content-skew__txt-inner js-11-2">
                      <h2>タイトル</h1>
                        <p>テキストテキストテキストテキスト</p>
                    </div>
                  </div>
                  <img class="js-11-3" src="https://picsum.photos/1000?random=4" alt="">
                </div>
              </div>
              <div class="content-skew__wrap js-cont-4">
                <div class="content-skew__box">
                  <div class="content-skew__cover js-12-1"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__cover js-12-2"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__txt">
                    <div class="content-skew__txt-inner js-12-3">
                      <h2>タイトル</h1>
                        <p>テキストテキストテキストテキスト</p>
                    </div>
                  </div>
                  <img class="js-12-4" src="https://picsum.photos/1000?random=5" alt="">
                </div>
              </div>
              <div class="content-skew__wrap js-cont-5">
                <div class="content-skew__box">
                  <div class="content-skew__cover js-13-1"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__txt">
                    <div class="content-skew__txt-inner js-13-2">
                      <h2>タイトル</h1>
                        <p>テキストテキストテキストテキスト</p>
                    </div>
                  </div>
                  <img class="js-13-3" src="https://picsum.photos/1000?random=6" alt="">
                </div>
              </div>
              <div class="content-skew__wrap">
                <div class="content-skew__box">
                  <div class="content-skew__cover js-14-1"></div><!-- /.content-skew__cover -->
                  <div class="content-skew__txt">
                    <div class="content-skew__txt-inner js-14-2">
                      <h2>タイトル</h1>
                        <p>テキストテキストテキストテキスト</p>
                    </div>
                  </div>
                  <img src="https://picsum.photos/1000?random=7" alt="">
                </div>
              </div>
            </div><!-- /.content-skew__inner -->
          </div><!-- /.content-skew -->
        </div><!-- /#main-container -->
      </main>
      <footer class="footer">footer</footer><!-- /.footer -->
    </div><!-- /#container -->
  </div><!-- /#global-container -->
</body>

</html>

解説

このHTMLコードは、ウェブページの基本的な構造を定義しており、さまざまな技術やスタイルを組み合わせて、ユーザーに視覚的に魅力的でインタラクティブな体験を提供することを目的としています。主要な要素について簡単に解説します。

ヘッダーセクション (head)

  • メタタグ: 文字コード(UTF-8)とビューポートの設定を含みます。ビューポートの設定は、ウェブサイトが様々なデバイスで適切に表示されるようにするためのものです。
  • 外部スタイルシートとスクリプト: ウェブサイトの見た目を整えるためのスタイルシート(destyle.cssstyle.min.css)と、動的なアニメーションやスクロール効果を追加するためのJavaScriptライブラリ(GSAPとScrollTrigger)を読み込んでいます。destyle.cssはデフォルトのスタイルをリセットし、クロスブラウザの一貫性を提供します。gsap.jsdefer属性を使用して遅延読み込みされ、ページの読み込み速度に影響を与えにくくしています。

ボディセクション (body)

  • HTML構造: ページは<div id="global-container">に全てのコンテンツを包含し、<header>,<main>, そして<footer>セクションに分かれています。これにより、ページの主要なセクションが明確に区切られます。
  • クラスとIDの使用: 要素にはID(例:#global-container,#main-container)やクラス(例:.content-skew,.content-skew__box)が割り当てられており、これによってCSSやJavaScriptで特定の要素を簡単にターゲットにすることができます。
  • インタラクティブ要素:js-で始まるクラス名は、JavaScriptで特定の動作やアニメーションを適用するために使用されることが示唆されます(例:.js-cont-1)。
  • コンテンツの表示: 各.content-skew__wrapはページ内のコンテンツブロックを表し、テキスト(<h2><p>タグ)と画像(<img>タグ)で構成されています。これらのブロックは視覚的に魅力的なレイアウトを作成し、ユーザーの注目を引きます。

外部リソース

  • GSAPとScrollTrigger: GSAP(GreenSock Animation Platform)は、高性能なアニメーションを実現するJavaScriptライブラリで、ScrollTriggerプラグインはスクロールに応じたアニメーションを可能にします。これらは、ページ上でスムーズでインタラクティブなスクロール効果を作り出すために使用されます。

全体として、このコードはモダンなウェブ開発技術を活用して、視覚的にも機能的にも豊かなウェブサイトを構築するための基礎を提供します。

CSS(SCSS)

header,
footer {
  background-color: #333;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
  font-size: 3rem;
  color: #fff;
}

#main-container {
  padding: 20% 0;
  max-width: 900px;
}

.wrap {
  width: 95%;
  margin: 0 auto;
}

.content-skew {
  h2 {
    color: #000;
    font-size: 2rem;
    font-weight: 700;
  }

  p {
    color: #000;
    font-weight: 700;
  }


  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }


  &__inner {
    row-gap: 30px;

    .content-skew {
      &__wrap {
        &:nth-last-of-type(even) {
            margin-left: auto;
        }

        &:nth-of-type(1) {
          .content-skew {
            &__cover {
              transition: 0.5s;
              width: 300%;
              height: 300%;
              position: absolute;
              right: 0;
              bottom: 0;
              background: #ccd3ca;
              transform: skew(45deg);
            }
          }
        }

        &:nth-of-type(1):hover {
          .content-skew {
            &__cover {
              transform: translateX(100%) skew(45deg);
            }
          }
        }

        &:nth-of-type(2) {
          .content-skew {
            &__cover {
              transition: 0.5s;
              width: 300%;
              height: 300%;
              position: absolute;
              top: 0;
              bottom: 0;
              background: #b5c0d0;
              transform: skew(-135deg);
            }
          }
        }

        &:nth-of-type(2):hover {
          .content-skew {
            &__cover {
              transform: translateX(-100%) skew(-135deg);
            }
          }
        }

        &:nth-of-type(3) {
          .content-skew {
            &__cover {
              transition: 0.5s;
              width: 200%;
              height: 200%;
              position: absolute;

              &:nth-of-type(1) {
                right: 0;
                bottom: 0;
                background: #ccd3ca;
                transform: skew(45deg);
              }

              &:nth-last-of-type(2) {
                top: 0;
                right: 0;
                background: #b5c0d0;
                transform: skew(-135deg);
              }
            }
          }
        }

        &:nth-of-type(3):hover {
          .content-skew {
            &__cover {
              &:nth-of-type(1) {
                transform: translateX(100%) skew(45deg);
              }

              &:nth-of-type(2) {
                transform: translateX(-100%) skew(-135deg);
              }
            }
          }
        }

        &:nth-of-type(4) {
          .content-skew {
            &__cover {
              transition: 0.5s;
              width: 200%;
              height: 200%;
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              background: #ccd3ca;
              border-radius: 50%;
            }
          }
        }

        &:nth-of-type(4):hover {
          .content-skew {
            &__cover {
              width: 0;
              height: 0;
            }
          }
        }

        &:nth-of-type(5) {
          .content-skew {
            &__cover {
              transition: 0.5s;
              width: 0%;
              height: 0%;
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              background: #b5c0d0;
              border-radius: 50%;
            }
          }
        }

        &:nth-of-type(5):hover {
          .content-skew {
            &__cover {
              width: 200%;
              height: 200%;
            }

            &__txt {
              transition-delay: 0.5s;
            }
          }
        }
      }
    }
  }

  &__wrap {
    row-gap: 30px;
    width: 400px;
    height: 400px;
    line-height: 1.7;
    overflow: hidden;
  }

  &__box {
    position: relative;
  }

  &__txt {
    transition: 0.5s ease-out;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;

    &-inner {
      padding-top: 50px;
      width: 90%;
      margin: 0 auto;
    }
  }
}

解説

このCSS(Sass)コードは、ウェブページのスタイリングに関する詳細な設定を提供します。特に、ヘッダー、フッター、メインコンテナ、およびコンテンツの視覚的要素をデザインしています。重要なポイントを抜粋して解説します。

ヘッダーとフッター

  • 一貫したスタイリングを適用し、背景色(#333)、テキストの色(白)、フォントサイズ、およびフレックスボックスを使用した中央揃えを設定しています。

メインコンテナ

  • #main-containerに対してパディングと最大幅を定義し、コンテンツのレイアウトを整えています。

コンテンツスタイリング

  • .wrapクラスは、コンテンツのラッピングとマージンの調整に使われます。
  • .content-skew関連のスタイルでは、特に見出し(h2)、段落(p)、画像(img)に対してフォントサイズ、重さ、カラー、サイズ調整をしています。これにより、テキストと画像の視覚的魅力を高めています。

インタラクティブな要素

  • .content-skew__wrapとその子要素に対する様々なスタイル定義があり、特に:hover状態における動的な変化(例えば、サイズ、位置、変形の変化)を通じてインタラクティブ性を向上させています。
  • 特定の.content-skew__wrapの子要素に対しては、スクロールやホバーに応じて様々なアニメーション効果(例:transformの変更)を適用しています。これらは、ユーザーがコンテンツと対話する際の視覚的フィードバックを提供します。

位置とオーバーフロー

  • .content-skew__boxは相対位置に設定され、その子要素である.content-skew__txtは絶対位置に設定されており、テキストコンテンツの正確な配置を可能にします。
  • .content-skew__wrapに設定されたoverflow: hidden;は、その中のコンテンツが指定されたサイズを超えた場合に見えなくなるようにしています。

このコード全体を通じて、ウェブページに洗練された、インタラクティブで視覚的に引きつけられるデザインを実現するための詳細なスタイル定義が行われています。

Javascript(Gsap)

const animation1 = gsap
  .timeline({
    scrollTrigger: {
      trigger: ".js-cont-1",
      start: "80% 10%",
      markers: true,
    },
  })
  .to(".js-10-1", {
    x: "100%",
    skew: "45deg", // skew(45deg)をskewXとして正しく指定
  })

  .from(".js-10-3", {
    y: 10,
    opacity: 0,
  })
  .from(".js-10-2", {
    opacity: 0,
  });

const animation2 = gsap
  .timeline({
    scrollTrigger: {
      trigger: ".js-cont-2",
      start: "80% 10%",
      markers: true,
    },
  })
  .to(".js-11-1", {
    x: "-100%",
  })

  .from(".js-11-3", {
    y: "-10px",
    opacity: 0,
  })
  .from(".js-11-3", {
    filter: "blur(5px)",
  })
  .from(".js-11-2", {
    opacity: 0,
  });

const animation3 = gsap
  .timeline({
    scrollTrigger: {
      trigger: ".js-cont-3",
      start: "80% 10%",
      markers: true,
    },
  })
  .to(".js-12-1", {
    x: "100%",
  })
  .to(
    ".js-12-2",
    {
      x: "-100%",
    },
    "<="
  )

  .from(
    ".js-12-4",
    {
      opacity: 0,
      scale: 0.8,
    },
    "-=0.2"
  )
  .from(".js-12-3", {
    opacity: 0,
  });

const animation4 = gsap
  .timeline({
    scrollTrigger: {
      trigger: ".js-cont-4",
      start: "80% 15%",
      markers: true,
    },
  })
  .to(".js-13-1", {
    width: "0",
    height: "0", // skew(45deg)をskewXとして正しく指定
  })
  .from(".js-13-2", {
    opacity: 0,
  });

const animation5 = gsap
  .timeline({
    scrollTrigger: {
      trigger: ".js-cont-4",
      start: "80% 15%",
      markers: true,
    },
  })
  .to(".js-14-1", {
    width: "200%",
    height: "200%", // skew(45deg)をskewXとして正しく指定
  })
  .from(".js-14-2", {
    opacity: 0,
  });

解説

このJavaScriptコードは、GSAP (GreenSock Animation Platform) ライブラリを使用して、ウェブページ上でスクロールに応じたアニメーションシーケンスを定義しています。各アニメーションは、特定の要素に対して動きや透明度の変化などの効果を適用することにより、ユーザーのインタラクションに応答します。以下に主要なポイントをまとめて解説します。

GSAPのtimelinescrollTrigger

  • gsap.timeline()は、複数のアニメーションを時系列に沿って連続して実行するためのタイムラインを作成します。
  • scrollTriggerは、特定の要素がビューポート内の指定された位置に到達したときにアニメーションをトリガーするためのオプションです。triggerはアニメーションが開始される要素を指定し、startはトリガー要素とビューポートの位置関係を定義します。markersは開発時にスクロールトリガーの位置を視覚的に表示します。

アニメーション詳細

  • .to()メソッドは、指定されたCSSプロパティを変更して要素をアニメーションさせます(例:x軸沿いの移動、skew変形)。
  • .from()メソッドは、アニメーションの開始状態を設定し、指定されたプロパティからアニメーションを逆再生します(例:透明度opacity、位置y軸の変化)。

各アニメーションの概要

  • animation1:.js-cont-1をトリガーとして、要素.js-10-1x軸に100%移動させ、skewX変形を加え、その後に複数の要素の透明度を0から1へ変化させます。
  • animation2:.js-cont-2で同様に、要素を移動させ、透明度やフィルター効果(blur)を適用してアニメーションします。
  • animation3:.js-cont-3をトリガーに、2つの要素を対照的に移動させ(一つはx軸に100%、もう一つは-100%)、別の要素に対して透明度とスケール変化のアニメーションを適用します。
  • animation4とanimation5: これらは.js-cont-4をトリガーにしており、サイズ変更(widthheightの変化)や透明度のアニメーションを含みます。

これらのアニメーションは、ウェブページのユーザーエクスペリエンスを向上させ、訪問者に対してより動的で魅力的なコンテンツを提供することを目的としています。

まとめ
  • Gsapは高性能アニメーションである
  • 広範なブラウザ互換性
  • 豊富な機能とコントロール
  • シンプルなAPIと使いやすさ
  • イージング効果の多様性