JavaScriptライブラリの「GSAP」(ジーサップ)は、ウェブサイトのモーション制作に役立ちます。第1回では、GSAPの基本的な使い方を解説しました。
第2回となる本記事では、タイムラインによる演出を紹介します。
タイムライン
タイムラインはGSAPで高度な演出をつくるうえで必ず利用する重要な機能です。
複雑なモーションを時系列で作成できるので、多くのトゥイーンを作成したり、管理するのに便利です。
▼公式サイトのチュートリアル動画。たった5行のコードで出現アニメーションを構築。

使い方として、gsap.timeline()で作成したインスタンスに対して、add()メソッドでタイムラインにgsap.to()のトゥイーンを追加します。
const tl = gsap.timeline({ repeat: -1, repeatDelay: 0.5 }); // はじめに初期化
// 続けて動かしたい要素を追加
tl.add(gsap.to(".rect", { x: 100, duration: 1 })); // 水平方向に移動
tl.add(gsap.to(".rect", { y: 100, duration: 1 })); // 垂直方向に移動
tl.add(gsap.to(".rect", { rotation: 360, duration: 1 })); // 回転
tl.add(gsap.to(".rect", { x: 0, duration: 1 })); // 水平方向に移動
tl.add(gsap.to(".rect", { y: 0, duration: 1 })); // 垂直方向に移動
タイムラインのto()メソッドはadd(gsap.to())のショートカットであるため、以下の記述でも利用できます。
const tl = gsap.timeline({ repeat: -1, repeatDelay: 0.5 }); // はじめに初期化
// 続けて動かしたい要素を追加
tl.to(".rect", { x: 100, duration: 1 }); // 水平方向に移動
tl.to(".rect", { y: 100, duration: 1 }); // 垂直方向に移動
tl.to(".rect", { rotation: 360, duration: 1 }); // 回転
tl.to(".rect", { x: 0, duration: 1 }); // 水平方向に移動
tl.to(".rect", { y: 0, duration: 1 }); // 垂直方向に移動
チェーンメソッドとして記述してもいいでしょう。いずれの記述も書き方が異なるだけで、実行結果に違いはありません。
gsap
.timeline({ repeat: -1, repeatDelay: 0.5 }) // はじめに初期化
// 続けて動かしたい要素を追加
.to(".rect", { x: 100, duration: 1 }) // 水平方向に移動
.to(".rect", { y: 100, duration: 1 }) // 垂直方向に移動
.to(".rect", { rotation: 360, duration: 1 }) // 回転
.to(".rect", { x: 0, duration: 1 }) // 水平方向に移動
.to(".rect", { y: 0, duration: 1 }); // 垂直方向に移動
メソッド
タイムラインの作成で主に利用にするのは以下のメソッドです。
| 関数名 | 説明 |
|---|---|
| add() | トゥイーン、タイムライン、コールバック、ラベルをタイムラインに追加します。 |
| to() | gsap.to()トゥイーンをタイムラインの最後に追加します。 |
| from() | gsap.from() トゥイーンをタイムラインの最後に追加します。 |
| fromTo() | gsap.fromTo() トゥイーンをタイムラインの最後に追加します。 |
| set() | タイミングで値をセットします。 |
| call() | タイミングで関数を呼び出します。 |
時間指定
モーションは直列でつないでいくと台本的な動きになりがちです。滑らかに演出を見せるためには、モーションを重ねることが多いです。次の作例では、前半は台本的な動きとし、後半は重ねつつモーションさせています。
gsap
.timeline({ repeat: -1, repeatDelay: 0.5 })
// 🌟段取り的なうごき
.set("h1", { textContent: "show" })
.from(".rect1", { y: -32, opacity: 0, duration: 0.5 })
.from(".rect2", { y: 32, opacity: 0, duration: 0.5 })
.from(".rect3", { y: -32, opacity: 0, duration: 0.5 })
.from(".rect4", { y: 32, opacity: 0, duration: 0.5 })
.from(".rect5", { y: -32, opacity: 0, duration: 0.5 })
.from(".rect6", { y: 32, opacity: 0, duration: 0.5 })
// 🌟ここから重ねつつ動かしている
.set("h1", { textContent: "hide" }, "+=1") // 1秒待機
.to(".rect1", { y: -32, opacity: 0, duration: 0.5 }, "+=0.5") // 0.5秒待機
.to(".rect2", { y: 32, opacity: 0, duration: 0.5 }, "-=0.4") // 0.4秒開始を早める
.to(".rect3", { y: -32, opacity: 0, duration: 0.5 }, "-=0.4")
.to(".rect4", { y: 32, opacity: 0, duration: 0.5 }, "-=0.4")
.to(".rect5", { y: -32, opacity: 0, duration: 0.5 }, "-=0.4")
.to(".rect6", { y: 32, opacity: 0, duration: 0.5 }, "-=0.4");
タイムラインのタイミングはto()やfrom()メソッドの第3引数positionで指定可能です。
数値を指定すると、タイムラインの先頭からの絶対時間になります。"+=2"はタイムライン末尾の2秒後、"-=2"はタイムライン末尾の2秒前に配置します。
+=や-=の直後にパーセンテージを指定すると、挿入するアニメーションの総時間が基準になります。たとえば"-=50%"は、挿入するアニメーションの総時間の50%だけタイムライン末尾に重ねます。直前に追加したアニメーションの50%の位置に配置する場合は、"<50%"と指定します。
時間指定で数値以外に指定できるもの
| 値 | 具体値 | 説明 | 頻出度 |
|---|---|---|---|
数値 |
1 |
タイムラインの先頭からの時間(秒)で開始 | ★ |
+=数値 |
+=1 |
タイムライン末尾の何秒後か | ★ |
-=数値 |
-=1 |
タイムライン末尾の何秒前か | ★ |
< |
< |
直前に追加したアニメーションの開始時 | ★ |
<数値 |
<1 |
直前に追加したアニメーションの開始から何秒後か | |
> |
> |
直前に追加したアニメーションの終了時 | |
>数値 |
>1 |
直前に追加したアニメーションの終了から何秒後か |
筆者としては「★」の習得をオススメします(それ以外は個人的にあまり使わないです)。
他にもさまざまな指定方法があるので、公式解説の『Timeline Tip: Understanding the Position Parameter - Learning Center - GreenSock』を参照ください。
ネスト
タイムラインはネスト(入れ子)も可能です。GSAPのタイムラインを作るとコードが長くなってしまいがちです。ネストを上手に使ってコードを整理するといいでしょう。
タイムラインをgsap.timeline.add()メソッドで、別のタイムラインインスタンスを追加します。
// タイムラインを作成する関数
function createChildTimeline(target) {
const tl = gsap.timeline();
tl.to(target, { x: 100, duration: 1 });
return tl; // タイムラインを戻り値にする
}
// ルートのタイムラインを作成
const rootTl = gsap
.timeline()
.add(createChildTimeline(".a")) // 子どもを追加
.add(createChildTimeline(".b")); // 子どもを追加
ここまでで、タイムラインの重要な機能はひととおり紹介しました。
高度な制御
ここからは中・上級者向けのタイムラインの機能を紹介します。必ず利用するものではないので、初級者はスキップして構いません。
seek()
GSAPのタイムラインはtimeline.seek()メソッドでシークできます。一般的な用語として「シーク」とは、再生中の動画の好きな場所に再生位置を動かす操作のことです。
次のサンプルでは、シークバーをinputタグで用意しています。シークバーを動かして、GSAPのタイムラインの時間を自由に行き来できることを確認ください。再生速度も変更できます。
※デモはVue.jsを使ってインタラクティブに作成しています。
時間に関するタイムラインのメソッドを紹介します。time()・duration()・progress()はいずれもゲッター(取得)・セッター(設定)の役割として用意されています。
| 関数名 | 説明 |
|---|---|
| time() | 再生ヘッドのローカル位置(基本的には現在時刻)を取得または設定します(リピートやrepeatDelayは含まれません)。 |
| duration() | タイムラインの時間(秒)を取得します。セッターとして使用された場合、指定されたデュレーション内に収まるようにタイムラインのtimeScaleを調整します。 |
| progress() | タイムラインの進行状況を取得・設定します。0から1までの値で、仮想再生ヘッドの位置を表します(0が最初、0.5が半分、1が完了)。 |
| seek() | 特定の時間にジャンプします。 |
tweenTo()
タイムラインの時間軸に対してトゥイーンを適用できます。tweenTo()メソッドを利用します。複数のオブジェクトを制御するようなタイムラインにおいて、演出の工夫として使ってもいいでしょう。
// 格子状に適用
const tl = gsap
.timeline()
.from(".rect", {
scale: 0,
rotation: -360,
duration: 0.5,
stagger: {
each: 0.1,
grid: "auto", // 格子状に開始
},
})
.addLabel("complete"); // ラベルを追加
// 時間軸に対してトゥイーン
tl.tweenTo("complete", {
duration: 4,
// 時間軸に対してイージングを指定
ease: "slow(0.4, 0.9, false)",
// 注意:slow は EasePack プラグインの導入が必要
});
| 関数名 | 説明 |
|---|---|
| addLabel() | タイムラインにラベルを追加。重要な位置/時間を簡単にマークできます。 |
| tweenTo() | 再生ヘッドを特定の時間までスクラブし、その後停止するリニアトゥイーンを作成します。 |
timeScale()
タイムラインのtimeScale()メソッドを使うとタイムラインの再生時間を伸縮できます。タイムラインの伸縮を使えば、タイムラインの一部分だけスローモーションにできます。この演出の呼び方はいろいろあるのですが、私は「タイムリマップ」と呼んでいます。
タイムリマップ演出は当サイトの記事『GSAPを使ったタイムリマップ表現』で詳しく解説しています。

先ほど紹介したtweenTo()メソッドと演出が少し似ていますが、制御のアプローチが異なります。コードの書き方や演出のフレーバーが異なるので、好みで使い分けていいでしょう。
まとめ
タイムラインは複雑な演出を作るのに欠かせない機能です。
次の第3回では、ScrollTriggerを使ったスクロール演出を紹介します。複雑なスクロール演出では、複数のモーションをまとめるタイムラインが必要になります。
※この記事が公開されたのは3年前ですが、今月8月に内容をメンテナンスしています。


