JavaScript Udemy スキルアップ

【GSAP 2/4】基本的なアニメーションと連続した動きの実装ー初めてのTween作成編

本記事から本格的にGSAPを使ってアニメーションを作っていきます。

今回は主にGSAPの基本的なアニメーションの実装方法を解説します。

この記事はUdemyの「Master JavaScript Animations with GreenSock」という教材をもとにGSAPについて解説しています。

2時間30分の講座でGSAPの基本から応用までカバーされており、1日で自由にアニメーションを作れるようになります。

この記事では「Master JavaScript Animations with GreenSock」で説明がなかったり、個人的に疑問に思った部分を調べて解説しているのでUdemyをメインで使い、サポート教材としてこのブログを使うと抜け漏れなく学べるように作っています。

この記事だけでもGSAPを使ってアニメーションの実装ができるようにまとめています。

本記事を理解することで下記のようなかっこいいローディングアニメーションを実装することができます。(※Udemy講座の内容になります)

前回の記事でGSAP全体の特徴や概要を説明していますのでまずはそちらを読んでもらえると理解もスムーズかと思います。

あわせて読みたい

【GSAP 1/4】アニメーションが簡単に作られるJavaScriptライブラリ「GSAP」

続きを見る

この記事の筆者

フロントエンドエンジニア
Yamato

未経験から独学でフロントエンドエンジニアになりました。上場企業のWeb制作チームマネージャーを4年経験し、現在フリーランスをしながら法人を設立しフロントエンドとして活動しています。JS/WordPress/Vue/Shopifyが得意です。

では解説していきます!

まずは準備

実装を開始する前にHTML、CSS、JavaScriptをそれぞれ準備します。

ファイル構成は全ファイルが下記のように同一の階層になるようにします。

ではHTMLとCSSそれぞれ下記のコードをコピペしてください。(JavaScriptはファイルだけ作っておいてください)

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>GSAP</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    
    <div class="container">
      <div class="item square"></div>
      <div class="item circle"></div>
    </div>

    <script src="app.js"></script>
  </body>
</html>

CSS

.container {
  display: flex;
  justify-content: space-around;
  width: 100%;
  margin-top: 100px;
}
.square {
  width: 150px;
  height: 150px;
  background-color: green;
}
.circle {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background-color: red;
}

下図のような表示になると思います。

これでべースは完成です。

GSAPを導入する

GSAPを使用するためにまずは公式サイトからCDNでソースを読み込みます。

上記のページに遷移したら図の①のタブを選択し、②のリンクをコピーします。

そして先ほど作ったHTMLの15行目のapp.scriptの読み込みより上に記述します。

  <!-- ↓この一文を追加↓ -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script> 
  <!-- ↑この一文を追加↑ -->
    <script src="app.js"></script>
  </body>
</html>

これで全ての準備が整いました。😀
次から実際にアニメーションを作っていきましょう!

gsap.toとgsap.from

gsapオブジェクトで作るTween(アニメーション)の基本が次の2つです。

  • gsap.to
  • gsap.from

gsap.fromToもあるのですが、こちらはあまり使わないので、今回は説明を省略します。

gsap.toは"指定した状態に"アニメーションする

まずはgsap.toの説明からしていきます。

const square = document.querySelector('.square'); //←動かしたい要素を指定しています。
gsap.to(square, {
  x: 200,
  duration: 1,
});

このように記述してページをリロードすると、四角の要素が右に移動します。
「duration: 1」はアニメーションに何秒かけるかを指定しています。
今回だと「1秒間かけて右に200px移動する」という意味です。

デモページで確認

gsap.fromは"指定した状態から"アニメーションする

次にgsap.fromです。

const square = document.querySelector('.square'); //←動かしたい要素を指定しています。
gsap.from(square, {
  x: 200,
  duration: 1,
});

このように記述をすることで、右に200pxの位置からもとの位置に戻ってきます。
今はxを指定して横方向の移動ですが、xをyに変更すると縦方向のアニメーションに変わります。

デモページで確認

これらがGSAPでアニメーションを実装する超基本部分です。

イージングをつけて動き方に変化をつける

GSAPにはイージングの機能が備わっています。

イージングとはアニメーション中の動きに変化をつけることです。

指定方法は簡単で、公式ページでデモを見ながら決められます。

まずはこちらにアクセス(公式ページに遷移します)

右側の気になるイージングを①選択し、下の値を②コピペします。
今回はわかりやすイージングのbounceを指定したいと思います。

const square = document.querySelector('.square');
gsap.from(square, {
  x: 200,
  duration: 1,
  ease: 'bounce.out', // ◀︎ これを追記
});

デモページで確認

コピペで完結なので簡単ですね!

フェードアウト・フェードイン

フェードアウト・フェードインのアニメーションはautoAlphaというプロパティを使います。
autoAlphaはCSSの「opacity」と「visibility」の両方をコントロールしてくれます。

フェードアウト

const square = document.querySelector('.square');
gsap.to(square, {
  duration: 3,
  autoAlpha: 0,
});

デモページで確認

「autoAlpha: 0」と記述することで、「opacity: 0」と「visibility: hidden」が設定されました。

フェードイン

const square = document.querySelector('.square');
gsap.from(square, {
  duration: 3,
  autoAlpha: 0,
});

gsap.toをgsap.fromに変更しました。
fromに変えると「opacity: 0; visibility: hidden」から「opacity: 1; visibility: inherit;」にアニメーションされます。

つまり見えない状態から見える状態にアニメーションされるということです。

しかしフェードインの実装時には注意が必要です。

というのも今のJavaScriptファイルは記述量が少なく処理も少ないので、ほぼ問題なくフェードインが綺麗に見えますが、少し処理を増やすとフェードインが綺麗に見えなくなってしまいます。

次のデモを見て何度かリロードしてみください。

デモページで確認

リロードのたびに緑の要素が少し残り、そしてフェードインが始まります。
実はgsapの前にfor文を入れてある処理をさせているのです。

const square = document.querySelector('.square');

for (i = 0; i <= 4000; i++) {
  console.log(i);
}
gsap.from(square, {
  autoAlpha: 0,
  duration: 3,
});

for文で0〜4000までをカウントさせているだけです。
これだけでフェードインにチラつきが発生してしまいます。

なぜフェードインでチラつきが起こるのか?

理由は2つあります。

  • CSSでopacityやvisibilityを設定していなければデフォルトで「opacity:1; visibility: inherit;」になる
  • ソースが読み込まれる順番は基本的にHTML→CSS→JSの順になる


詳しく説明します。

まずHTML、CSSが読み込まれページが表示されます。

この時、「opacity」と「visibility」が設定されていなければCSSのデフォルト値である「opacity:1; visibility: inherit;」の状態になります。

つまりHTML・CS Sが読み込まれた時点では対象要素はユーザーには見えている状態です。

次にJSファイルが読み込まれ、for文の4000のカウントが始まります。

for文の処理が終わればgsap.fromの処理が始まり、一度対象要素は「autoAlpha: 0」つまり「opacity: 0; visibility: hidden」になり、徐々に「opacity: 1; visibility: inherit;」にアニメーションされます。

つまり、HTML、CSSが読み込まれページが表示されてから次にJSファイルが読み込まれ、さらにJSファイル内のgsapの処理が始まるわずかの間は対象の要素は「opacity:1; visibility: inherit;」の状態になっているのです。

これがチラつきの正体です。

このチラつきを無くすにはCSSに初めから「visibility: hidden;」を設定します。
「visibility: hidden;」だけで要素が見えなくなるので、opacityの設定は不要です。

.square {
  width: 150px;
  height: 150px;
  background-color: green;
  visibility: hidden; //◀︎ 追加
}

これでリロードしてもチラつきがなくなります。
下のデモページで確認しましょう。

デモページで確認(チラつき無し)

stagger:グループ内の要素を順番に動かす

次はあるグループを作ってその中で順番にアニメーションをさせてみましょう。
今回は四角と丸の要素を順番にフェードインさせます。
まず先ほどと同様に丸の要素に「visibility: hidden;」を指定します。

.square {
  width: 150px;
  height: 150px;
  background-color: green;
  visibility: hidden;
}
.circle {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background-color: red;
  visibility: hidden; //◀︎ 追加
}

次にgsapにstaggerプロパティを追加します。

const items = document.querySelectorAll('.item'); //◀︎ グループの全要素を指定

gsap.from(items, {
  autoAlpha: 0,
  duration: 3,
  stagger: {
    each: 1,
  },
});

stagger内にeachを設定することでアニメーションが発生する間隔を指定しています。
この記述だと「1秒間隔で発生」させています。

デモページで確認

今は左から順番にアニメーションしていますが、アニメーションのスタート位置も調整できるので詳しくはこちらをチェックしてください。

1つの要素を連続して動かす

一つの要素を「右に100px移動させ、次に下に100px移動させ、また右に100px移動させる」ような連続したアニメーションを設定する方法です。

CSSを変更します。

.square {
  width: 150px;
  height: 150px;
  background-color: green;
  /* visibility: hidden; */ //◀︎ コメントアウト
}
.circle {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background-color: red;
  /* visibility: hidden; */ //◀︎ コメントアウト
}

次にapp.jsを触ります。
「右に100px移動させ、次に下に100px移動させ、また右に100px移動させる」動きなので下記のように記述します。

const square = document.querySelector('.square');

gsap.to(square, { duration: 1, x: 100 });
gsap.to(square, { duration: 1, y: 100 });
gsap.to(square, { duration: 1, x: 200 });

しかしこれだと一気に斜めにアニメーションしてしまいます。

デモページで確認

keyframes

連続したアニメーションを作る時はkeyframesを使い配列の中に、アニメーション内容を上から順番に記述します。

gsap.to(square, {
  keyframes: [
    { duration: 1, x: 100 },
    { duration: 1, y: 100 },
    { duration: 1, x: 200 },
  ],
});

デモページで確認

トリガーとコールバック

GSAPではTweenの中にトリガーとコールバックを設定できます。

よく使うトリガーは4つあって、
・onStart:アニメーションスタート時
・onUpdate:アニメーション中
・onComplete:アニメーション完了時
・onRepeat:リピート開始時

です。

下記のコードでは1回のリピートが発生するように記載しています。

const square = document.querySelector('.square');

gsap.to(square, {
  x: 200,
  duration: 3,
  repeat: 1, //◀︎ リピートの指示
  onStart: () => console.log('アニメーション開始!'),
  onUpdate: () => console.log('アニメーション中'),
  onComplete: () => console.log('アニメーション終了!'),
  onRepeat: () => console.log('リピート開始'),
});

イベントの発火タイミングを動画で見てみましょう。

デモページで確認

Tween(アニメーションの塊)の保存

Tweenは保存することができます。

保存にはregisterEffect()メソッド、使用時にはgsap.effectsオブジェクト

下記のコードでは2秒後に保存したアニメーションが動き出すように記述しています。
複雑そうに見えますが、一行一行見れば理解できます。

const square = document.querySelector('.square');

gsap.registerEffect({  //◀︎ registerEffect()メソッド
  name: 'squareAnimation', //◀︎ 登録名を指定
  effect: (targets, config) => { //◀︎ 実際の挙動をコールバックで記述
    return gsap.to(targets, {
      duration: config.duration,
      y: 200,
      scale: 1.4,
      rotation: 360,
    });
  }
});

setTimeout(() => {
  gsap.effects.squareAnimation(square, { duration: 5 }); //◀︎ gsap.effectsオブジェクトを使用し、後ろに登録時につけた登録名を、さらにターゲットと独自の設定(今回はduration)を記述
}, 2000);

デモページで確認

Tweenを変数に保存

Tweenは変数にも保存可能です。

const square = document.querySelector('.square');
const tween = gsap.to(square, { y: 200, paused: true });

setTimeout(() => {
  tween.play();
}, 2000);

注意点としては、保存するTweenに「paused: true」を忘れないことです。
これを忘れてしまうと、変数に保存されたアニメーションでも変数が読み込まれたタイミングでアニメーションが開始されてしまいます。

5行目のplay()メソッドはpausedで止められていたアニメーションを開始させるメソッドです。

デモページで確認

GSAPのメソッドを上手に繋げて使えば、アニメーション時間や開始時間の遅延の調整もできます。

const square = document.querySelector('.square');
const tween = gsap.to(square, { y: 200, paused: true });

setTimeout(() => {
  tween.play().duration(5).delay(1);
}, 2000);

使えるメソッドはたくさんあるので、こちらをチェックしてください。

まとめ

本記事はGSAPの基本となる部分を解説しました。
次は複数の要素と連動させたアニメーションを作るTimelineについて解説します。

では今回は以上です!
ほな🙌🏻

あわせて読みたい

【GSAP 3/4】Timelineを使って複数の要素を連動させるアニメーション

続きを見る

-JavaScript, Udemy, スキルアップ