search
LoginSignup
3

posted at

updated at

GSAPを使ったオープニングアニメーションの作り方

突然ですが、GSAPというライブラリを聞いた事はありますか?

今回使うサンプル

スクリーンショット 2022-10-26 16.05.35.png

GSAPとは

アニメーションを実装するために特化したライブラリですね。

GSAPを導入する(NPMで導入する)

$ npm install gsap

また、TypeScriptの型定義ファイルもgsapパッケージに同梱されているので、@typesの導入は不要です。

GSAPを導入する(CDNで導入する)

GSAPをサクッと導入したい場合は下記scriptタグをコピペしてください。

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.0/gsap.min.js"></script>

GSAPの基本的な書き方

基本的にGSAPを扱うときは下記のメソッドを使います。

gsap.set();
gsap.to();

それぞれ解説していきます。

①要素の状態をセットするgsap.set()

まず、はじめにアニメーションさせたい要素にアニメーション前の状態をセットします。

gsap.set(対象のDOM, {
   プロパティ
})

②要素をある状態に変化させるgsap.to()

アニメーションをここで定義します。

gsap.to(対象のDOM, {
   プロパティ
})

例(フェード系)

フェード系はCSSで言うところのopacityを使います。GSAPでも同じなので早速簡単な例を見ていきましょう。
今回例として取り上げさせていただくのはよくあるローディング画面です。使用しているプロパティはopacitydurationです。
それ以外のプロパティはご自身で確かめてください。

See the Pen gsap-opacity-sample by Watataku (@watataku8911) on CodePen.

プロパティ 説明 単位 デフォルト値(括弧内はデフォルト値)
duration 時間 数値(秒) 省略化(1.0)
ease 加減速 文字列か関数 省略化(power2.inOut)
repeat リピート回数 数値(秒) 省略化(0)
repeatDelay リピートするまでの遅延 数値 省略化(0)
delay 遅延秒数 数値(秒) 省略化(0)
overwrite 上書きするか 真偽値 省略化(false)
paused 一時停止した状態にするか 真偽値 省略化(false)
yoyo リピート時に反復挙動にするか 真偽値 or "auto" 省略化(false)

repeatプロパティを-1に指定すると無限に繰り返すになる。

例(スライド系)

スライド系を実装する場合はCSSプロパティのtransformを使いますよね?
GSAPでも同じです。GSAPではCSSのtransformを直感的に記述できます。

See the Pen gsap-slide-sample by Watataku (@watataku8911) on CodePen.

※演出上の都合で、全てのボックスに`duration`と`repeat`をかけています
GSAP CSS 説明
x: 20 transform: transformX(20px) 水平方向への移動(px)
y: 20 transform: transformY(20px) 垂直方向への移動(px)
rotate: 360 transform: rotate(360deg) 回転角度(角度)
scale: 2 transform: scale(2, 2) 拡大・縮小(1.0が等倍)
scaleX: 2 transform: scaleX(2) 水平方向だけ拡大・縮小
scale:Y 2 transform: scaleY(2) 垂直方向だけ拡大・縮小
xPercent: -50 transform: translateX(-50%) 水平方向への移動(要素の幅に対する割合)
yPercent: -50 transform: translateY(-50%) 垂直方向への移動(要素の幅に対する割合)

タイムライン

アニメーションを繋げたい時に使います。

const tl = gsap.timeline();
tl.to(".selector1", {
  selector1のアニメーション
}).to(".selector2", {
  selector2のアニメーション
});

selector1のアニメーションが終了後、selector2、3とアニメーションする。

イージング


本題

ここで、ようやく図のようなサンプルを作っていきます。
今回はHTMLとCSSは解説しませんがコードだけ貼っておきます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div class="c-loader-bg js-loader-bg">
      <div class="c-loader-dot js-loader-dot-wrap">
        <span></span>
        <span></span>
        <span></span>
      </div>
    </div>
    <!-- ヘッダー -->
    <header class="c-header js-header">
      <div class="c-temp">
        <p class="text">[ GSAP DEMO ]</p>
        <p class="link">
          <a href="https://b-risk.jp/blog/2022/05/gsap/" class="button"
            >Button</a
          >
        </p>
      </div>
    </header>

    <div class="cursor"></div>

    <div class="shapes">
      <div class="shape shape1"></div>
      <div class="shape shape2"></div>
    </div>

    <div class="l-inner">
      <div class="c-mv_title-wrap">
        <div class="c-mv_title">
          <h1 class="c-mv_title-item js-mv_title-item">Hello Would!!</h1>
        </div>
      </div>
    </div>

    <script type="module" src="/main.js"></script>
  </body>
</html>

JS

まず、はじめに要素を取得しておきます。

const jsLoaderBg = ".js-loader-bg";
const jsDot = ".js-loader-dot-wrap > span";
const shapes = ".shape";
const jsText = ".js-mv_title-item span";
const jsHeader = ".js-header";

次に、アニメーションをセットし「アニメーション始めま〜す」と宣言します。

gsap.set([shapes, jsText], {
  opacity: 0,
  y: 30,
});
gsap.set(jsHeader, {
  opacity: 0,
  y: -50,
});
gsap.set(jsDot, {
  opacity: 0,
  y: -50,
});

最後に、gsap.to()でアニメーションの処理を書いていきます。

const tl = gsap.timeline();

/* ドットが左から0.5秒おきに降ってくる */
tl.to(
  jsDot,
  {
    opacity: 1,
    y: 0,
    duration: 0.8,
    delay: 0.8,
    stagger: {
      amount: 0.5, //0.5秒おきに
      from: "start", // 左から
      ease: "power4.inOut",
    },
  }
)

/* 全てのドット(今回3つ)が出尽くした後ドットを消す */
.to(jsDot, {
  opacity: 0,
})
 
/* ドットが消えた後カーテンが上から開く */
.to(jsLoaderBg, {
  y: "100%",
  delay: 0.5,
})

/* カーテンが開くと0.2秒後に下から円が登場 */ 
.to(
  shapes,
    {
      opacity: 1,
      y: 0,
      duration: 0.8,
      stagger: {
        amount: 0.6,
        from: "start",
        ease: "sine.in",
     },
    },
   "+=0.2" // dealy: 0.5と同じ
)

/* 円が登場後「HelloWould」が1文字ずつ登場 */
.to(
   jsText,
    {
      opacity: 1,
      y: 0,
      stagger: {
        amount: 1,
        from: "start",
        ease: "sine.in",
     },
    },
   "-=0.1"  // 前のアニメーションが完了する0.1秒前に実行する書き方
)

/* 文字が登場後ヘッダーが上から参上!! */
.to(jsHeader, {
  opacity: 1,
  y: 0,
});

CSSはGithubをご覧ください。

文字列を分割しspanで囲む

これはGSAPと直接関わりはないのですが、Hello Wouldと一文字一文字アニメーションさせるためにspanタグで囲みます。

/* 文字列を分割しspanで囲む */
(function () {
  const jsText = document.querySelectorAll(".js-mv_title-item");
  jsText.forEach((target) => {
    let newText = "";
    const text = target.textContent;
    const result = text.split("");
    for (let i = 0; i < result.length; i++) {
      newText += "<span>" + result[i] + "</span>";
    }
    target.innerHTML = newText;
  });
})();

今回のサンプルの全体的なコード

最後に

このようにGSAPを扱うと複雑なアニメーションの処理も簡単に実装する事ができ、リッチなサイトが簡単に作れるので是非使って見てください。

この記事を読んでGSAPについて少しでもわかっていただけたら幸いです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3