本格的なタイムラインアニメが作れる最強ライブラリーTimelineMaxの使い方

2017/08/29

Maria Antonietta Perna

62

Articles in this issue reproduced from SitePoint
Copyright © 2017, All rights reserved. SitePoint Pty Ltd. www.sitepoint.com. Translation copyright © 2017, KADOKAWA ASCII Research Laboratories, Inc. Japanese syndication rights arranged with SitePoint Pty Ltd, Collingwood, Victoria,Australia through Tuttle-Mori Agency, Inc., Tokyo

JavaScriptでFlashライクなWebアニメーションを作れる「GreenSock」。タイムラインを使った本格的なアニメーションの作り方、思い通りに動かすコツを解説します。

GreenSockのTimelineMaxを紹介し、以下の項目を説明します。

  • タイムラインの必要性
  • タイムラインに複数のトゥイーンを含める方法
  • 複数のタイムラインを関数にまとめ、マスタータイムラインにネストすることで柔軟性を高める方法

チュートリアルを読めば、GreenSockのタイムラインを使って複数のトゥイーンを思いのまま扱えます。

TweenMaxを使って単純なアニメーションをつなぎ合わせる方法や連続で動かす方法などのGreenSockの基礎知識はさよならFlash!いまこそ学ぶWebアニメライブラリー「GreenSock」入門を読んでください。

WebアニメーションのコーディングにGreenSockのタイムラインが必要な理由

この記事では、単独または複数の要素にさまざまなアニメーションを追加する方法を説明しました。独立したトゥイーンをいくつか作成し、各トゥイーンのdelayプロパティでトゥイーン間のタイミングを調整して実現しました。

デフォルトでは、トゥイーンの後ろに別のトゥイーンを並べると、すべてのトゥイーンが同時に動作します。トゥイーンを起動させるタイミングをほかのトゥイーンと連動(例:同時、1秒前に、0.5秒後に)すると効果的です。

2つのトゥイーンを使った簡単な例で考えます。

  • トゥイーン1:円が拡大縮小しながらX軸、Y軸方向に回転する
  • トゥイーン2:文字がポップアップする

この処理を実行するGSAPのスニペットです。

// scale down the text 
// and hide it before the animation begins 
TweenMax.set('.example__title', { 
  scale: 0.2, 
  autoAlpha: 0
});

// scale the circle shape down before 
// the animation begins
TweenMax.set('.example__ball', {
  scale: 0.2
});

// tween 1
TweenMax.to('.example__ball', 0.5, {
  rotationX: 360,
  rotationY: 180,
  scale: 1,
  ease: Elastic.easeIn.config(2, 1)
});

// tween 2
TweenMax.to('.example__title', 0.5, {
  autoAlpha: 1,
  scale: 1,
  ease: Back.easeOut.config(4)
});

両方のトゥイーンが同時に動作します。望ましいエフェクトではありません。

図形の回転が止まってから文字を表示するには、トゥイーン2に適切な待ち時間を追加します。

// tween 2
  TweenMax.to('.example__title', 0.5, {
  // rest of the code here
  delay: 0.6
});

これでも動きますが、最初のトゥイーンの持続時間やリピート回数を変更すると、2つ目のトゥイーンが最初のトゥイーンの終了を待たずに開始します。2つ目のトゥイーンのdelay値を調整します。トゥイーンが2つだけで、アニメーションが単純なら問題にはなりませんが、大掛かりなアニメーションはトゥイーンの数も増えるので、簡単にはいきません。

この問題を解決するのが、GSAPのTimelineLiteTimelineMaxです。どちらもTweenMaxにインクルードされている、堅牢で柔軟性の高いモジュールです。

GSAPのタイムラインを使って複数のトゥイーンを連動させる

タイムラインはトゥイーンや別のタイムラインを格納するコンテナのようなものです。タイムライン内で、トゥイーンは独立性を失い相互接続された状態になります。それぞれのトゥイーンが前のトゥイーンの完了後に実行されるのがデフォルトの処理で、持続時間やリピート回数を変更しても影響されません。

GreenSockのタイムラインを学ぶ最初のステップとして、上記スニペットのトゥイーンをタイムライン内に設置します。

コードは以下の通りです。

// instantiate TimelineMax
const tl = new TimelineMax();

// scale down the text 
// and hide it before the animation begins
tl.set('.example__title', { 
  scale: 0.2, 
  autoAlpha: 0
})
 // scale the circle shape down before 
 // the animation begins
 .set('.example__ball', {
  scale: 0.2
})
 // tween 1: rotate shape on X and Y axis
 // scale it up to its regular dimensions
 // add a fun ease
.to('.example__ball', 0.5, {
  rotationX: 360,
  rotationY: 180,
  scale: 1,
  ease: Elastic.easeIn.config(2, 1)
})
 // tween 2: make text appear and 
 // scale it up to its regular size
 // add a fun ta-da ease
.to('.example__title', 0.5, {
  autoAlpha: 1,
  scale: 1,
  ease: Back.easeOut.config(4)
});

最初にタイムラインのインスタンスを生成します。必要な機能に合わせてTimelineLiteまたはTimelineMaxを選択します。TimelineMaxにはTimelineLiteのすべての機能と、追加機能が備わっています。それぞれのモジュールで利用可能な機能の一覧は、GSAPのWebサイトTimelineMaxのページで確認できます。

上のスニペットではTimelineMaxのインスタンス「tl」を生成します。コードの動作には関係ないので、好きな名前をつけます。

インスタンスを生成したあとは、メソッドto()、from()、fromTo()を使用できます。

上のコードではアニメーションを開始する前にset()を使って要素の値を調整しています。タイムライン上でもTweenMaxでset()を使ったときと同様このメソッドを使えます。要素のプロパティに値を設定すると、時間の経過とともにアニメーションで変更が反映されるのではなく、瞬時に変更が反映されます。set()の詳しい使用方法はドキュメントページを確認してください。

コードの残りはTweenMaxを使って書いたものと変わりません。唯一の違いはTimelineMaxのメソッドチェインを使っている点です。GSAPの構文は一貫しているため、効率良く学習できます。

図形のアニメーションの終了直後に文字が表示されるのですが、コードをみてもdelayプロパティがありません。タイムラインにトゥイーンを追加する際、ディレイを使って各トゥイーンを連携させる必要はないのです。

GreenSockのTimelineMaxポジションパラメータ

トゥイーンを自動的に連続で実行できるの便利ですが、前のアニメーションが完了する0.5秒前から、または完了後数秒たってから次の要素をアニメーション動作させたい場合はどうするのでしょうか? アニメーションの値を再調整せずに実現するには、ポジションパラメータを使います。パラメータを追加するにはvars {}オブジェクトのあとに相対値(-=0.5, +=2)を使います。

-=1を追加するとタイムラインにおける手前のトゥイーンが終わる1秒前にトゥイーンを起動します。 +=1を追加すると手前のトゥイーンが終わってから1秒後にトゥイーンを起動します。

1をはじめ絶対値もポジションパラメータの値に使えます。値はトゥイーンが起動するまでの正味の時間を秒で指定します。

簡単な例を示します。

.to(box1, 1, {
  rotation: 45,
  transformOrigin: 'center bottom',
  ease: Elastic.easeOut
})
.to(box2, 1, {
  rotation: -45,
  transformOrigin: 'center bottom',
  ease: Elastic.easeOut
})

上のスニペットは、タイムライン内で2つの要素を互いに逆方向に回転しています。

ポジションパラメータがない場合、box1のアニメーション完了後すぐにbox2のアニメーションが始まります。

両方のトゥイーンを同時に開始するには、2つ目のトゥイーンの波括弧を閉じたあとにコンマを追加し、ポジションパラメータ'-=1'を追加します。

.to(box1, 1, {
  // code here
})
.to(box2, 1, {
  // code here
}, '-=1') //position parameter

最初のトゥイーンは1秒間動作するので、ポジションパラメータ'-=1'を使ってアニメーションを1秒前倒しすると両方のトゥイーンが同時に始まります。

以下はポジションパラメータを用いたアニメーションです。上記のコードを拡張しています。

ポジションパラメータの値にラベルを使う

数値の代わりにラベルを使用すれば、より柔軟で直感的な方法でポジションパラメータを操作できます。ラベルはタイムラインに追加し、あとで各トゥイーンから参照します。また、ラベルはコードよりはるかに読みやすいので、複雑なアニメーションに向いています。

タイムラインでトゥイーンのタイミングを取るための参照ポイントは.add()メソッドで意な文字を持つラベルを追加します。TimelineLiteTimelineMaxのどちらでも同じです。

tl.add('nameoflabel');

追加したラベルをポジションパラメータとして使います。

// move element horizontally 100px
tl.to(element, 0.5, {
  x: 100
})
.add('go') // add a label
// move element vertically 100px
// with reference to the 'go' label
.to(element, 1, {
  y: 100
}, 'go');
// rotate otherElement 
// with reference to the 'go' label
.to(otherElement, 0.5, {
  rotation: 360
}, 'go');

上のスニペットは、elementを右に100px移動させて、アニメーションが終了すると、goラベルを参照しているelementanotherElementが同時にアニメーションを開始します(ラベルにはアニメーションに関連した意味のある名前をつけます)。

ラベルは相対値と組み合わせて使えます。たとえば、elementの2秒後にotherElementを起動したい場合は、ポジションパラメータを'go+=2'とします。

以下のデモでは、アニメーションの一部(例:ロボットの手を振る動作、口の動き、吹き出しに関連するアニメーション)はすべてのポジションパラメータにラベルを用いてタイミング調整をしています。

GSAPのWebサイトにある専用ページには、ポジションパラメータについてのさらに詳しい情報が載っています。

GreenSockのマスタータイムラインを使ってコードを体系的に管理する

これまで見てきたデモは説明用の例としては十分ですが、グローバルスコープでコードを書くには不十分です。アニメーションが単純なときは、タイムラインを関数に格納し適宜呼び出せば問題ありません。

複雑なケースのために、GSAPにはマスタータイムラインが用意されています。マスタータイムラインは通常のタイムラインにほかのタイムラインをネストさせたもので、コードの体系的な管理や、コードのメンテナンス性、柔軟性の確保において重要な役割を果たします。

タイムラインのネストは以下の通りです。

// timeline-based animation inside a function
function partOne() {
  // timeline instance
  const tl = new TimelineMax();
  
  // add your tweens to the timeline as usual
  tl.to(myElement, 0.5, {
    rotation: 90,
    ease: Back.easeOut
  })
    .to(otherElement, 1, {
    // more code here
  });
  
  // return the timeline instance
  return tl;
}

// create a new timeline instance 
const master = new TimelineMax();

// add your function and a label to it
master.add(partOne(), 'part1');

上のスニペットでは、タイムラインを使ったアニメーションを関数に格納しています。関数名は一連のアニメーションを表すもの、または単にpartOnesceneOneなど自由に設定できます。次にGSAPのTimelineLiteまたはTimelineMaxのインスタンスを生成し、これまで同様トゥイーンを追加、タイムラインのインスタンスをreturn tlで返します。

最後に、マスタータイムラインのインスタンスを作成してから.add()を使って関数をインクルードし、関数を呼び出します(関数名の括弧を忘れないでください)。

スニペットではラベルも追加しています。ラベルはマスタータイムラインを管理するのに便利な機能です。詳しくは次の章で説明します。

関数内でタイムラインを作りマスタータイムラインに追加することで、より多くのタイムラインを扱えます。タイムラインがモジュール化されているため、理解しやすいコードになり、柔軟性も向上します(たとえば、タイムラインを呼び出す順番や、タイムライン間のタイミングを容易に変更できます)。

以下のデモでは、マスタータイムラインを使ってアニメーションをホストしています。アニメーションは4つのタイムラインに分割され、別々に関数に格納されています。

GreenSockのタイムラインアニメーションで使えるテクニック

GreenSockのタイムラインにはWebアニメーターの作業を楽にする優れた機能が備わっています。これらの機能を活用したテクニックを紹介します。

ページ読み込み時にすべてのGSAPトゥイーンをポーズさせる方法

タイムラインで相互接続されている各トゥイーンをまとめてコントロールします。

ページ読み込み時はすべてのトゥイーンをポーズさせて、ボタンクリックでアニメーションを開始したいなら、GSPAのタイムラインで、インスタンス生成時にコードを1行追加するだけで実現できます。

const tl = new TimelineMax({ paused: true });

同様に、マスタータイムラインをポーズすると、ネストされたタイムラインがまとめてポーズします。

const master = new TimelineMax({ paused: true });

複数のGSAPトゥイーンをまとめて再生、ポーズ、リスタート、逆再生させる方法

この記事ではplay()、pause()、reverse()、restart()、resume()を使ってトゥイーンを個別にコントロールする方法を説明しました。同じメソッドでタイムライン全体をコントロールしたりネストされたタイムラインを(マスタータイムラインを通して)コントロールしたりできます。

たとえば、あるタイムライン内のトゥイーンシーケンス全体を再生するなら、以下の通りです。

tl.play();

上のCodePenデモの一部では、restart()を使ってタイムラインを操作することでReplayボタンを実装しています。

複数のGSAPトゥイーンをまとめてスローダウン/スピードアップさせる方法

トゥイーンをタイムライン内にラップすることで、アニメーション全体のスピードをわずかなコードで変更できます。アニメーションをスローダウンします。

tl.timeScale(0.3);

ネストされたタイムラインには以下の通りです。

master.timeScale(0.3);

.timeScale()メソッドはアニメーション時間の倍率を設定します。値が1のときは通常速度(デフォルト)に設定され、0.5のときは半分、2のときは2倍に設定されます。

この機能は、高速に再生されるアニメーションの動きをチェックする場合や、特定のトゥイーンを超スローモーションで詳細に確認する場合に重宝します。GreenSockの.timeScale()を使うことで、タイムライン内のタイミングを操作しなくてもアニメーションの動きを確認できます。

アニメーションをGSAPタイムラインの決まった場所から再生する方法

Webアニメーションの作成は、1つのトゥイーンを納得のいく形になるまで何度も調整します。トゥイーンが複雑なアニメーションの途中、または最後にある場合、アニメーション全体を何度もリプレイするのは大変です。

GSAPの.seek() メソッドとラベルを使うことで、アニメーションをタイムラインの好きな場所から始められます。マスタータイムラインにネストされたタイムラインについても同様です。前章でをタイムラインに「part1」のラベル追加した理由です。

3つのタイムラインをネストしたマスタータイムラインを考えます。

const master = new TimelineMax();

master.add(partOne(), 'part1')
      .add(partTwo(), 'part2')
      .add(partThree(), 'part3');

調整したい箇所がアニメーションの中盤にあり、調整のために変更箇所を何度もテストする必要があるなら、以下のスニペットでアニメーションは「part2」から始まります。アニメーションのシーケンス全体を繰り返し再生するという面倒な作業が不要になります。

master.seek('part2');

また、「part2」の3秒後からアニメーションを開始したい場合は、ラベルに相対ポジションパラメータをつけます。

master.seek('part2+=3');

調整したい箇所からアニメーションを始められるので、ストレスを感じることなく何度でもテストできます。

最後に

GreenSockのTimelineMax()とネストされたタイムラインの操作方法を説明しました。タイムラインは堅牢で柔軟性のある、Webアニメーションを作成するための豊富なコントロール機能を持ったライブラリーです。タイムラインの力を借りることで、洗練されたアニメーションシーケンスを素早く組み立てられます。

次回はCodePen上でGSAPのプレミアムプラグインを使う予定です。それまでの間、デモをどれか1つフォークしてポジションパラメータの値を微調整したり、タイムラインにトゥイーンを追加したり、順序を逆にしたり、タイムラインに慣れ親しんでください。

「Beyond CSS: Dynamic DOM Animation Libraries(動的DOMアニメーションライブラリー)」シリーズ

(原文:GreenSock for Beginners (Part 2): GSAP’s Timeline

[翻訳:薮田佳佑/編集:Livit

Copyright © 2017, Maria Antonietta Perna All Rights Reserved.

 Maria Antonietta Perna

Maria Antonietta Perna

SitePointのHTML/CSSチャンネルの共同編集者・フロントエンドWeb開発者です。CSSでいろんな手法を試すことを楽しんでいます。また、フロントエンドのプログラミング指導方法にも興味を持っています。コーディングやWeb関連の執筆をしていないときは、哲学書や散歩、おいしいものを楽しんでいます。

Loading...