AOS.js・IntersectionObserver・GSAPでアニメーション制御する方法


Webサイト制作において、スクロールに応じて要素をアニメーションさせる表現は今や定番です。この記事では、代表的なアニメーションライブラリである AOS.jsIntersection Observer API(以下IO)、そして圧倒的な表現力を誇る GSAP(GreenSock Animation Platform) を活用し、発火タイミングを自在にコントロールする方法を紹介します。


サンプルコード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>GSAP / IO / AOS</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" rel="stylesheet" />
    <style>
      body {
        margin: 0;
        padding: 0;
        padding-bottom: 200vh;
        font-family: sans-serif;
        background: linear-gradient(to bottom, #0d0d0d 0%, #010d00 30%, #0c0f40 100%);
        background-attachment: fixed;
      }

      .scroll {
        color: #787878;
        position: absolute;
        font-size: 16px;
        writing-mode: vertical-rl;
        top: 40%;
        left: 50%;
        transform: translate(-50%, -50%);
      }

      .scroll::after {
        content: "";
        display: inline-block;
        position: absolute;
        background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #00f, #0ff);
        left: calc(50% - 1px);
        transform: translateX(0);
        bottom: -115px;
        width: 1px;
        height: 100px;
        animation: scroll 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;
      }

      @keyframes scroll {
        0% {
          transform: scale(1, 0);
          transform-origin: 0 0;
        }
        50% {
          transform: scale(1, 1);
          transform-origin: 0 0;
        }
        50.1% {
          transform: scale(1, 1);
          transform-origin: 0 100%;
        }
        100% {
          transform: scale(1, 0);
          transform-origin: 0 100%;
        }
      }

      section {
        min-height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-top: 100vh;
      }

      /* AOS専用 */
      .aos-box {
        background: #f0f0f0;
        padding: 50px;
        font-size: 1.5rem;
        max-width: 600px;
        margin: 0 auto;
      }

      /* IO専用 */
      .io-box {
        background: #ffe8e8;
        padding: 50px;
        font-size: 1.5rem;
        max-width: 600px;
        margin: 0 auto;
        opacity: 0;
        transition: opacity 0.6s ease;
      }

      .io-box.active {
        background: #d4f8d4;
        opacity: 1;
      }

      /* GSAP専用(共通クラスなし) */
      .gsap-box {
        background: #e0f7ff;
        padding: 50px;
        font-size: 1.5rem;
        max-width: 600px;
        margin: 0 auto;
        opacity: 0;
      }
    </style>
  </head>
  <body>
    <div class="scroll">
      <p>scroll</p>
    </div>
    <!-- ✅ GSAP(独立クラス) -->
    <section>
      <div class="gsap-box">✅ GSAP:画面下30%で表示</div>
    </section>

    <!-- ✅ IO(独立クラス) -->
    <section>
      <div class="io-box">✅ IntersectionObserver:クラス付与で表示</div>
    </section>

    <!-- ✅ AOS(独立クラス) -->
    <section>
      <div class="aos-box" data-aos="fade-up" data-aos-anchor-placement="top-bottom">✅ AOS.js:画面下30%で表示</div>
    </section>

    <!-- Scripts -->
    <script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.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>
      // ✅ AOS 初期化
      AOS.init({
        offset: 0,
        duration: 800,
        once: true,
      });

      // ✅ IO 初期化
      const ioTargets = document.querySelectorAll(".io-box");
      const io = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              entry.target.classList.add("active");
            }
          });
        },
        {
          rootMargin: "0px 0px -30% 0px",
          threshold: 0,
        }
      );
      ioTargets.forEach((el) => io.observe(el));

      // ✅ GSAP ScrollTrigger
      gsap.registerPlugin(ScrollTrigger);

      gsap.fromTo(
        ".gsap-box",
        { opacity: 0, y: 50 },
        {
          opacity: 1,
          y: 0,
          duration: 1,
          scrollTrigger: {
            trigger: ".gsap-box",
            start: "top 70%",
            toggleActions: "play none none none",
          },
        }
      );

      ScrollTrigger.refresh();
      setTimeout(() => AOS.refreshHard(), 500);
    </script>
  </body>
</html>

1. スクロールアニメーションに使える3大ライブラリの特徴

ライブラリ概要得意なこと
AOS.jsHTML属性ベースでアニメーションを設定できる軽量ライブラリfade、zoom、slideなどの基本的な演出を簡単に設定可能
Intersection Observer APIブラウザ標準のスクロール検知機能。ライブラリ不要の純粋なJavaScript要素が画面に入ったかどうかを高精度で監視し、任意の処理を実行できる
GSAP + ScrollTriggerハイパフォーマンスなJavaScriptアニメーションライブラリピクセル単位での細かいトリガー制御、複雑なアニメーション表現が可能

スクロールアニメーションを美しく演出するために、これらを適材適所で使い分けることで、UXを損なわずに滑らかで直感的な演出が実現できます。


2. 発火タイミングを制御する重要性

アニメーションがいつ始まるか(=発火タイミング)はユーザー体験に直結します。たとえば、要素が画面に表示された瞬間に fade-up で滑らかに現れる演出は、注目を集めるための視覚効果として有効です。

  • AOS.js は data-aos-offset を使って「画面下30%」「画面下40%」などの柔軟な位置での発火が可能
  • Intersection Observer では rootMargin を使うことで、正確なトリガー位置を調整
  • GSAP + ScrollTrigger では start 値でスクロールの発火条件を細かく設定

アニメーション発火のタイミング設計は、ユーザーの注目を集めるための非常に重要なポイントとなります。


3. 使用シーンに応じた活用方法

✅ AOS.js:手軽にフェードやズームなどの演出を追加

AOS(Animate On Scroll)はHTMLに data-aos 属性を追加するだけで簡単に使えるスクロールアニメーションライブラリです。特に、静的なページにアニメーションを加えたいときに便利です。

  • 例:data-aos="fade-up"data-aos-offset="40vh" など
  • 軽量かつ導入が簡単なため、LP(ランディングページ)や商品ページでの演出に適しています

✅ Intersection Observer API:状態制御や遅延処理に強い

純粋なJavaScript機能であるIntersection Observerは、特定の要素が画面に入ったかどうかを監視できます。これにより、アニメーションだけでなく、カウンターや読み込み処理、ナビゲーション切り替えなど、インタラクティブなUI制御にも応用できます。

  • rootMarginthreshold を使った緻密なトリガー制御が可能
  • ライブラリ不要でパフォーマンス面でも有利

✅ GSAP + ScrollTrigger:複雑な演出や連動表現に最適

GSAP(GreenSock)はJavaScriptで高精度かつ高性能なアニメーションを作れる定番ライブラリです。ScrollTriggerプラグインと組み合わせることで、スクロールに応じた高度な連動アニメーションが可能になります。

  • スクロール位置によるズーム、回転、ピン留め演出
  • startendscrubpinなどの詳細設定が可能
  • インタラクティブなWebサイトやポートフォリオに最適

4. 使用パターン別おすすめライブラリ

使用シーン目的推奨ライブラリ
テキストやボックスのfade表示初期表示の演出AOS.js
ヘッダーやUIの状態切り替えナビゲーションや通知表示Intersection Observer
セクション全体の動きやズームビジュアル表現やインパクト重視のページGSAP + ScrollTrigger

✅ まとめ:スクロールアニメーションを戦略的に使い分けよう

スクロールに応じたアニメーションは、ユーザーの視線を誘導し、UXを向上させるための非常に重要な施策です。

  • 手軽に導入できるAOS.jsでデザインに動きをプラス
  • 状態制御が必要な場面ではIntersection Observerでロジック制御
  • 表現力が求められる演出にはGSAP + ScrollTriggerで洗練された動きを追加

これらを組み合わせることで、直感的かつ印象的なWeb体験を提供できます。

今後のWeb制作において、これらのアニメーション手法を戦略的に活用することで、見た目と機能の両立した魅力的なサイト制作が実現できます。

おすすめ記事:AOS.jsの使い方とサンプルLP|初心者でも簡単スクロールアニメーションを実装

おすすめ記事:ScrollReveal.jsの使い方とサンプルLP|簡単スクロール演出を実装

✪ 画像素材がないものはランダムで表示されるようになっています。フリー素材などでご用意ください。

おすすめChromeプラグイン一覧

プラグイン名特徴
GoFullPageウェブページ全体のスクリーンショットを簡単に取得できるブラウザ拡張機能です。
ColorZilla色を抽出するための拡張機能です。
WhatFontウェブページ上のフォントの情報を簡単に確認できるブラウザ拡張機能です。
PerfectPixelデザイナーが作成したデザインと実際にコーディングされたウェブページがどの程度一致しているかを確認・調整するためのブラウザ拡張機能です。

模写の手順

ステップ内容
ステップ 1構図を手書きか全画面スクショ(Go full page等)した後、ペイントツールで四角で囲い、大まかなclass,命名規則をあらかじめ決める。
ステップ 2HTMLの基本構造を作成する
ステップ 3CSSでレイアウトを模写する
ステップ 4 中級〜JavaScriptを追加して動きを再現する
ステップ 5最終調整を行い、検証ツールやPerfectPixel(chromeプラグイン)などで完成を確認する。