イージングとはなにか第1回目はシンプルなサンプルでイージングのコードで行われていることを解説します。どのような値を、どのように操作することでイージングが実現されているのか、その仕組みの理解を目指します。時間経過と値の変化をグラフにする変化の割合に変化を与えるまとめJavaScriptでなんらかのUIを作ることが多いという人の場合、イージングがどのように動作しているかを知らずとも、それを普段から利用している人は多いでしょう。イージングの仕組みはなかなか複雑です。この仕組みを理解したとしても、自らイージングを書くような機会はほぼないでしょう。普段利用しているアニメーションというものがどのようにできているのか知ることで、よりUIプログラミングへの理解を深めることができるかと思います。このシリーズで使うサンプルのコードは、以下に置いてあります。GitHubイージングってこんなやつまずはイージングがどんなものか見てみましょう。以下のデモを開き、Runと書かれたボタンを押してみてください。アニメーションを確認することができます。イージングとは[Run]ボタンをクリックすると、それぞれに設定されたイージングで赤い要素が動く。GitHubこのデモは、色のついたspanのleftをアニメーションさせていますが、このとき、それぞれに別のイージングを指定しています。このサンプルで、アニメーションを行わせている部分のコードは、以下のようになっています。'easeOutExpo');jQueryのanimateを実行する時、3番目の引数を指定すると、その指定した種類のイージングでアニメーションが行われます。ここで指定している各イージングについては、以下のような結果をもたらします。linear:常に同じ速度swing:始めはおだやか、途中はちょっと速め、最後はおだやかeaseInExpo:始めはとてもゆっくり、最後はとても速くeaseOutExpo:始めはとても速く、最後はとてもゆっくりここで使われているイージングのうち、linearとswingは、始めからjQueryに内蔵されているものです。アニメーションをさせるとき、なにも指定しなければ、自動的にswingが適用されます。イージングの追加方法easeInExpoとeaseOutExpoは、jQueryへイージングを追加するライブラリを読み込むことで、利用可能となります。UIに内蔵されているイージングのコードを読み込ませています。UIに内蔵されているイージングの一覧は、次から参照できます。Pluginでしょう。1.3)イージングの中身さて、上記のようなイージングのライブラリを読み込むとなにが起こるかというと、jQuery.easingに存在しているオブジェクトが拡張されます。アニメーション時にイージング名を指定すると、jQuery.easingを参照し、対応するイージング関数が適用されるようになっているのです。これらを読み込めば、jQueryのアニメーションとして指定できるイージングの種類が増えます。そのjQuery.easingの拡張が行われている箇所を見てみます。UIのコードの一部です。})();さて、このコードでなにが行われているのかわかるでしょうか。多くの人は、ここで書かれている処理がなんなのか、よくわからないのではないでしょうか。正直なところ筆者自身も、このコードのうち簡単なものしか理解できていませんが、このシリーズでは、このイージング関数内でどのような行われているのか、その基本的な仕組みを解説します。元祖イージング?このシリーズ自体、筆者がイージングの仕組みを理解していなかったので、調べ出したところから始まっているのですが、調べていたら、イージングの元祖とでもいうような人がいることがわかりました。Pennerという、Flashのデベロッパーです。氏のイージングに関する資料は、以下のページにまとまっています。Functionsはっきりとした起源はわからなかったのですが、どうやら、世の中に存在するイージングは、氏の考えたイージングそのものであるか、そのバリエーションであるものが多いようです。Pennerという名前が出てきます。そのイージングとはどういったものなのか。その仕組みを、簡単なサンプルとともに見ていくとしましょう。アニメーションまずはイージングを理解しやすくするため、自前でアニメーションの仕組みを実装してみます。以下が、そのデモです。イージングを用いたアニメーションデモ[Run]ボタンをクリックすると、1秒かけて赤いdiv要素が動く。GitHubこのデモでは、Runと書かれたボタンを押すと、1秒かけて赤いdiv要素が動きます。ここでは、leftの値を変化させていますが、その動きにイージング処理は施していません。左から右へ常に一定の速度で動きます。このサンプルのコードを見てみましょう。});});animateという関数にjQueryオブジェクトを渡すと、その要素のleftの値が、200(px)になるまで、1秒かけてアニメーションします。細かくパフォーマンスのことを追求すると、いろいろと改良の余地はありますが、ひとまず、今回はこのシンプルなサンプルを解説していきます。JavaScriptでのアニメーションの仕組みまずJavaScriptでアニメーションを行う場合、それがどのように行われるかを簡単に説明しておきます。映像などのアニメーション(動画)と同様に、JavaScriptでアニメーションを行う場合も、少しずつ状態が変化する静止画(コマ)を連続して表示し、動いているように見せる方法を使います。JavaScriptには、アニメーションを簡単な指定で実現するような機能を持ちあわせていません。このため、ごく短い時間間隔をおきながら、少しずつ要素のスタイルを変化させるという処理をイチから書く必要があります*。これがJavaScriptでアニメーションを行う際の一般的な実装方法です。「処理をイチから書く」といっても、私たちはそのようなアニメーションの処理を行いたいときは、jQueryなどのライブラリを使います。jQueryをはじめとしたライブラリが用意してくれているアニメーションの機能は、裏側でこのような実装を行っているものがほとんどです(もしくはCSSによるアニメーションを利用します)。この時、コマ送りの1コマ分のことを、1フレームといいます。1フレームを表示しておく時間を短くすればするほど、アニメーションがなめらかになります。jQueryでは、1フレームを13ミリ秒として扱っていますので、このサンプルでも同様に13ミリ秒にしました。それを指定しているのが、次の部分です。13;1フレームが13ミリ秒ということは、1秒は1000ミリ秒ですので、1000÷13で約77フレーム毎秒ということになります*。77回のステップを経て、1秒のアニメーションが実現される計算です。*注:フレームレート(fps)このように単位時間に何フレームを表示する(処理するか)を表す値をフレームレートと呼ぶことがあります。Second(fps)という表記もします。このサンプルの場合、アニメーションを実行すると、13ミリ秒ごとにleftの値を変化させるような処理が走り、経過時間が1000ミリ秒を超えると、このアニメーションは止まるようになっています。この値を小さくすればするほど、1フレームの表示時間が減るので、スムーズにアニメーションしているように見えます。注:setTimeoutの正確性MILLISEC_PER_FRAMEが13のところを、1にすれば、アニメ—ションが非常になめらかになるのではないかと想像されますが、実は、実際のところはそんなことはありません。1にしても、おそらくたいして変わっていないように見えるはずです。これというのは、JavaScriptのsetTimeoutが、指定された処理を、その時間が経過した時に実行することを約束するものではないためです。setTimeoutで13ミリ秒後になにかの処理を実行させる場合でも、そのときに、他のさまざまな処理が走っており、ブラウザの処理が追いつかなかった場合は、その分、遅れます。jQueryでたくさんのアニメーションを同時に走らせるような場合、アニメーションが遅れたりすることがありますが、それは、これが原因です。HTML5では、setTimeoutに4以下の数値を指定しても、それを4として扱うような仕様もあります(参考)。ほとんどのブラウザは、アクティブでないタブで走っているJavaScriptの処理速度を、著しく落とします。このためsetTimeoutが刻む時間は、非常にゆっくりになります。setTimeoutが、完全に正確な時間を刻むわけではないという点は、頭の片隅にでも入れておくとよいでしょう。ちなみに最近のブラウザには、よりアニメーションに利用しやすい、requestAnimationFrameという機能が備わっています。興味のある方は調べてみるとよいでしょう。animate関数の実装では、このアニメーションの実装を見てみましょう。animate関数の中身です。過ぎた時間まずはアニメーションに必要な変数を用意します。valueInChangeは変化させたいleftの値、durationは、アニメーションにかける時間(ミリ秒)です。1000ミリ秒かけてleftの値を200にするため、これを変数として用意しておきます。elapsedTimeは、時間経過を保存しておくための変数、leftValは、leftの値を一時的に保存しておくための変数です。次は、この中で作っているtickという関数を見てみます。このtickは、1フレーム分の動きを表現しています。これが繰り返し呼ばれることでアニメーションになるのですが、まずはその時間の仕組みを実現している部分だけをみてみます。動かし始めるanimate関数を呼ぶと、このtick関数が呼ばれます。その中で最後、setTimeoutを使い、13ミリ秒後に再びtickを呼んでいます。このようにして、繰り返しtickが呼ばれ続けます。このままだと永遠にループしてしまいますので、tickの処理の中で、経過時間を変数elaspsedTimeに加算していきます。これが1000を超えると、1秒経ったことになりますのでreturnしてループを止めます。leftの値の変化の実装では次に、このtickの中で、要素のleftを変化させている場所を見てみます。この部分は、イージングとも深く関わってくる部分です。};経過時間であるelapsedTimeは、始めは0、1度tickが呼ばれると13、2度めは26、3度めは39...と加算されていき、これが1000(durationの値)を超えるとアニメーションは終わります。経過時間であるelapsedTimeをトータル時間であるdurationで割ると、経過した時間の割合が計算できます。elapsedTimeは1000を超えることはないので、この値は0から1の間の値になります。これを変数elapsedTimeRateに保存しています。この値はアニメーション完了にかかる時間を1とした時、今どのくらいの時間が経ったのかという割合です。0〜1の範囲で、経過時間の割合を表現しています。アニメーションが完了した時、leftの値は200(valueInChange)になります。均一にleftの値が増えていくようにするのならば、tickが呼ばれた時、設定すべきleftの割合は、最終的に指定する200に経過時間の割合を掛けあわせれば求めることができます。その時点でのleftの値をスタイルとして要素に設定します。これが、前述のコードで行っている処理です。時間経過と値の変化をグラフにするここでもうひとつ、値の変化割合valueChangeRateという値を考えます。これはアニメーション完了時のleftの値200を1としたとき、現時点での値の割合です。200で1ですから、経過時間の割合と同様、0〜1の範囲で値の変化割合を考えます。経過時間の割合(elapsedTimeRate)をX軸、値の変化の割合(valueChangeRate)をY軸とすると、次のようなグラフになります。X座標、Y座標ともに、最小値0、最大値1のグラフとなり、均一な変化のグラフとなります。GitHubelapsedTimeRateと、valueChangeRateは、どのタイミングでも常に同じ値となっています。動かしているだけなので当たり前ですが......。均一に値を変化させるだけのことについて、なにを細かく説明しているんだと感じられるかもしれません。今解説した考え方は、イージングを理解する上で重要です。アニメーション中に「経過時間に応じて、どのように値の変化の割合を決めるか」というのが、イージングだからです。変化の割合に変化を与えるでは次に、変化の割合が均一ではないアニメーションを考えてみます。次に示すのは、イージングeaseInQuadを適用した場合のグラフです。easeInQuadを適用したアニメーションは「最初ゆっくり、最後速く」になります。GitHubこの動きは、先ほどの変化が均一なアニメーションに、わずかばかりの変化を加えるだけで実現できます。このサンプルで値を変化させている部分は、次のようになっています。num)は、xをnum乗した値を返します。均一な変化のサンプルでは、経過時間の割合elapsedTimeRateと値の変化の割合valueChangeRateは、まったく同一でした。時間が半分進めば、経過時間の割合elapsedTimeRateは0.5、このとき、均一にアニメーションさせるのであれば、leftは半分まで進んでいるのですから、値の変化の割合valueChangeRateも0.5です。今回はelapsedTimeRateを2乗したものを、変化の割合としています。ここでelapsedTimeRateは、アニメーション中、0〜1の範囲の値となります。1以下の数字を2乗すれば、それが小さい値であればあるほど、その結果の値は小さくなります。elapsedTimeRateが0.5であるとき、ひとつ前のサンプル(03-graph)では、valueChangeRateも0.5でした。今回のサンプルでは、それを2乗するのですから、0.25です。これは0.5の半分となりますので、均一な変化の時よりも、変化の割合が少ないということになります。elapsedTimeRateが0.1であるとき、0.1の2乗ということは、その0.1倍の数となりますから、その結果は0.01。0.1と比較すると、ずっと小さい値です。この値を大きくしていき、elapsedTimeRateが1に近い値の場合、例えば0.9のときを考えてみると、0.9の2乗は0.9の0.9倍ですから、0.81。0.9とはそうかけ離れた値にはなりません。elapsedTimeRateが1であれば、1の2乗は1の1倍ですから、この値は1です。このようにひとつずつ考えていくと、上記のように、ゆるやかに加速していくようなグラフとなり、このように値が変化していくアニメーションは「始めゆっくり、最後速く」となります。このように経過時間の割合elapsedTimeRateに、なにかしらの処理を施し、値の変化の割合valueChangeRateを決定するという仕組みがイージングです。この処理を担う関数のことをイージング関数と呼びます。今のサンプルに適用した処理をイージング関数として分けると、次のように表すことができます。valueChangeRate;easeInQuadのquadはquadraticの略で、辞書によれば「二次の」とありました。二次関数を利用したイージングということでしょう。ちなみに、始めのサンプルにあった均一な変化は、次のようなイージングで表すことができます。elapsedTimeRate;};経過時間の割合がそのまま値の変化の割合になるので、均一な変化となります。早い話、なにも変化を付けないということです。これは、linearという名前のイージングとして、始めからjQueryに内蔵されています。まとめ今回はイージングの仕組みをいくつかのデモを通して解説しました。イージングとはなにか、イージング関数の中でどんな処理が行われているのか、シンプルな例で見てもらいました。次回はこの基礎を踏まえた上で、引き続きイージングについて見ていきます。壮フロントエンド・エンジニアWeb制作会社、フリーランスを経て、株式会社ピクセルグリッドに入社。Webサイト、WebアプリケーションのHTML、CSS、JavaScript実装に携わってきた。受託案件を中心にフロント周りの実装、設計、テクニカルディレクションを行う。スケーラビリティを考慮したHTMLテンプレート設計・実装、JavaScriptを使った込み入ったUIの設計・実装を得意分野とする。jQuery入門』(技術評論社、2014年11月14日)がある。2013ベストセッションでは、全278セッション中、ベスト20セッションに選出。特定商取引法に基づく。