Closed16

GSAPさわる

ピン留めされたアイテム
masa5714masa5714

このスクラップは GSAP公式のGetting Startedを見ながら、自分なりに解釈した内容です。ネットの情報をコピペで感覚で使ってると発展性ないので、 Getting Started だけでも読んでおくと全然違います。なんか自信湧きます。

この文章は自分用のものなので正確性は保証しません。


【ひとりごと】
GSAPとは関係ないが、JS標準にはWeb Animation APIというものがある。
このサイト のメインビジュアルのふわふわ表現に使われているのだが、DOM操作されてもおらず、CSSにAnimationやKeyframesが一切書かれていない。JSファイル内に .animate という関数で書かれている。

Web Animation APIのリファレンス

timelineもあったりと今後はGSAP無しで実装できるようになる可能性も高い。しかし、数年後レベルのまだまだ先の話だと思われるので、GSAPを大人しく使うのが正しい判断だろう。

masa5714masa5714

トゥイーン

gsap.to(".box", { 
  x: 200,
});

上記は .box を右方向に 200px 動かすコード。
アニメーションしながら動く。

この単一の動きを「トゥイーン」と呼ぶ。

masa5714masa5714

トゥイーンの種類

全部で4種類ある。

  • gsap.to() : 基本的なトゥイーン。現在の状態から指定した値まで動くアニメーション。
  • gsap.from() : 指定した値からスタートして、現在の状態まで動くアニメーション。 .to() の逆。flexboxなどで作った要素を下からニュッと出すときなどに使える。
  • gsap.fromTo(): 開始状態と終了状態を指定して動くアニメーション。
  • gsap.set(): アニメーションなしで瞬時に適用する。
masa5714masa5714

ターゲット

GSAPで操作したい要素をCSSセレクタ形式で指定。
document.querySelectorAll() で取得するのと同じ状態なので、1つだけ動かしたいときは注意。

gsap.to(".box", { 
  x: 200,
});

この場合、 class="box" が付与された要素すべてに右方向に200px動かすアニメーションが適用される。

ちなみに、 document.querySelector() で取得した要素を入れることもできる模様。

let square = document.querySelector(".square");
let circle = document.querySelector(".circle");
                                      
gsap.to([square, circle], { x: 200 })
masa5714masa5714

アニメーション化できるもの

ほとんどのものがアニメーション化することができる。
CSSプロパティはもちろんのこと、CSS変数や複雑な文字列も。(ここで指している「複雑な文字列」とは何かは書かれてない。推測すると、数字のカウントダウンやランダム文字列がガーッと出力される演出とか?)

masa5714masa5714

GSAP特有の短縮表記

下記のCSSを例にする。

transform: rotate(360deg) translateX(10px) translateY(50%);

これは360度回転し、右方向に10px動かし、Y方向に要素高さの50%分上に動かす記述。

GSAPでは下記のように表現できる。

gsap.to('.box', {
  rotation: 360, // CSS では rotate(360deg)
  x: 10, // CSS では translateX(10px)
  yPercent: 50 // CSSでは translateX(50%)
})

ちょっと厄介なのが yPercent
通常の単位は px なので x: 10 のようにするが、%で動かす場合は xPercentyPercent が使える。脳内で変換して読み替える面倒くささはある。

ちなみにこのアニメーションは 360度回転しながらX方向に10px進みながらy方向に50%動くのを同時に処理される。

GSAP公式が下記の表を用意してくれているので確認しよう。( リンク

単位を変更する

x: 200, // 200px右に動かす
x: "+=200", // 相対値として200px右に動かす
x: "40vw", // 40vw右に動かす。
x: () => window.innerWidth / 2, // 計算結果の値で出た数値px分右に動かす

rotation: "1.25rad" // 1.25ラジアン回転
masa5714masa5714

SVGにも対応

SVGの図形もアニメションさせることができる。
SVGについては SVGアニメーションを使えばいいと思ってる派なので、ここは割愛する。

気になる人は、 詳しくはこちらのサンプルを確認してみよう。

masa5714masa5714

GSAPでよく使うオプション

https://greensock.com/get-started/#specialProperties

gsap.to('.box', {
  x: 200,
  duration: 3
})

上記コードでは duration がオプションに相当する。
よく使われるオプション(公式上の表記はプロパティ)は下記。

オプション名 単位 説明
duration ▶何秒かけてアニメーションをするか。
duration: 4 なら 4秒かけてアニメーション。
delay ▶アニメーション開始を待機。
delay: 4 なら 4秒後にアニメーションが開始。
repeat ▶アニメーションを何回繰り返すか。
repeat: 0 がデフォルトで1回。
repeat: 1なら合計2回実行。
repeat: -1 なら無限ループ
yoyo - ▶終わった後に逆再生。
yoyo: true で有効化。
ただし、repeat: 1 以上のときにしか動かないので注意。
stagger ▶複数要素を動かすときだけに使える。1つ目の.boxと2つ目の.boxとの実行の間隔を開けることができる。
stagger: 0.2 なら、同じ.boxでも0.2秒間隔を空けて実行される。
yoyo: true が有効になっている場合、逆再生時に一番最後のものから動くので注意。
ease - ▶イージング。デフォルト: power1.out
Easeで使える値はこちらを参照しよう。
イージングの選択はセンスが問われる。
自信が無ければ power4.out を選ぶとそれなりのものが作れるとか何とか?
onComplete - ▶アニメーションが終わったら何か処理を行うことができる。
repeat: -1 が適用されているときは動かない。
repeat: 1, yoyo: true のときは、逆再生まで終わってからonCompleteが動く。
masa5714masa5714

イージングの選び方

https://greensock.com/get-started/#easing

なんとGSAP公式さんが、どうやってイージングを選ぶと良いかを教えてくれています。

大きく分けて in / out / inOut の3種類ある。
これらは勢いの扱いをどうするかを示していると捉えるとイメージしやすいっぽい。

power1.in: 重いものが落ちるような感じ。ゆっくり始まり、早く終わる。
power1.out: 転がるボールがゆっくり止まる感じ。早く始まり、ゆっくり終わる。
power1.inOut: 車が加速して減速する感じ。ゆっくり始まり、ゆっくり終わる。

masa5714masa5714

タイムライン

https://greensock.com/get-started/#timelines

タイムラインを使えば、トゥイーンの処理が終わったら、次のトゥイーンを実行することができる。
前の動きが終わってから次の動きが始まる。

例えば、右方向に200px進んでから、下方向に200px進むこともできる。

上記の例をコードに書き起こすとこのようになる。

const boxTimeline = gsap.timeline();

boxTimeline.to(".box", { x: 100 });
boxTimeline.to(".box", { y: 100 });

まず gsap.timeline() でタイムラインを入れる箱を用意する。
この例ではタイムラインに boxTimeline という名前をつけた。
boxTimeline に boxTimeline.to(".box", {x:100}) を追加。
続けて boxTimeline.to(".box", {y: 100}) を追加。

たったこれだけで、

  • .boxがx:100 動く処理が終わったら
  • .boxがy:100 動く処理を実行できる。

タイムラインにもオプションを適用できる

const boxTimeline = gsap.timeline({
  repeat: -1,
  yoyo: true
});

boxTimeline.to(".box", { x: 100, y: 100 });
boxTimeline.to(".box", { y: "+=100" });
boxTimeline.to(".box", { y: "+=100" });

timelineの中にオプションを追加してやることができる。
なお、上記の例では translateYの値を +100 するような形にしている。
100px動いたあとに更に100px動かしたい(開始から見れば計200px)ので +=100 としている。ここで 学んだことが活きた。

実行の順番を変更する

ややこしくなるので極力使わない方向で行きたいが一応。

 boxTimeline.to(".box", { y: 100 });
 boxTimeline.to(".box", { x: 100 });

これが通常。下方向に100px進んだ後に横方向に100px動く。

では下記のように変更してみる。

boxTimeline.to(".box", { y: 100 }); // A
boxTimeline.to(".box", { x: 100 }, "<"); // B

この場合、下方向に100px進みながら横方向に100px動く。
"<" を入れることで、前のアニメーションと同時に実行を指示されるから。

別の書き方も見てみよう。

boxTimeline.to(".box", { y: 100 }); // A
boxTimeline.to(".box", { y: "+=100" }, "+=1"); // C

+=1 としている。 これは実行タイミングを1個ずらすことになる。
この場合、下方向に100px動いた後、1つのトゥイーン分何もせず待機してから、さらに100px下に動く。

何かアニメーションを実装したときに辛いときやってみると助かる機能かもしれない。

masa5714masa5714

基本は以上。
ここからは発展的なことをするための 「プラグイン」を見ていく。

masa5714masa5714

プラグインを適用する

そのままでは使えないので、コード上でプラグインの適用を記述する必要がある。

gsap.registerPlugin(MotionPathPlugin, ScrollTrigger, MorphSVGPlugin)

この記述では、MotionPathPlugin, ScrollTrigger, MorphSVGPlugin の3つのプラグインを有効化している。

masa5714masa5714

数字をカウントアップ

会社の歩みみたいな特設サイトにありがちな演出。

設立から今日までみたいな感じの。
検索で出てきた記事が応用を含んだ複雑なものだったので、超シンプルな形で書き残したかったの。

<p class="count-up">1800</p>
const target = document.querySelector(".count-up");

const nums = {
  hoge: 1800, // 初期値
};

gsap.to(nums, {
  hoge: 2023, // ゴール
  duration: 3,
  ease: "power4.out",
  onUpdate: () => {
    target.textContent = Math.floor(nums.hoge);
  },
});

hogeの部分は何でもOK。
初期値として 1800 を入れている。

hoge: 2023, は 2023 をゴールとする。
onUpdate は処理中にDOMへの出力を行っている。

これで完成。

カウントダウンをしたいなら、hogeの初期値を大きくして、ゴールを小さくするだけ。

masa5714masa5714

コンテンツの下からフッターが出てくるような表現

このスクラップをまとめる前は全く実装方法分からんかったが、今では余裕だ...。ドキュメント読むの大切すぎ!

ただし、この表現では一緒に動いている感があるので、完全にフッターの一番下から見えるよう、幕が上がる感覚の表現をするには、 position: fixed をして最下部に固定し、JSでフッターの高さを取得して、コンテンツに margin-bottom を適用することになる。

masa5714masa5714

ScrollTrigger

スクロールをトリガーにして何かする。
例えば、 .box 要素の中央にきたらアニメーションを開始するなど。

これらは ScrollTrigger で実装できる。


ScrollTrigger のオプションにスクロール量に反応しながら処理するというものがある。
これは上の埋め込みのフッターがコンテンツ下から出てくるような表現にも使っている。

scrub: true, を適用すると、スクロール量に応じて値が変わってくれる。
例えば、スクロールに応じてヘッダーメニューが上から出てきたり、ロゴのサイズを変更するときは、 scrub: true, を有効にすると良いだろう。

ポイントとして、
scrub: true する場合は ease: "none" をしておくべき。
これを忘れると、デフォルトのイージングが動いてしまいカクついてしまう。

このスクラップは2024/03/10にクローズされました