モバイル時代を生き抜くためのWebパフォーマンスモデル「RAIL」 ~Response、Animation、Idle、Loadから来る「速さの目安」を知って改善しよう!~

第5回(最終回) Webの「Animation(動き)」を改善しよう

最終回である今回は、Webの「Animation(動き⁠⁠」の改善方法について紹介します。

そもそもAnimationとは

まず、そもそもAnimationとはどのように実現するのか考えてみましょう。

多くの人は、テレビや映画がどのようにして映像を実現しているのかを理解しているはずです。一言でいえば「目の錯覚⁠⁠。静止画を短い期間で何度も差し替えると、画上の物体が動いているように目が錯覚するのです。そしてこれを、現実世界の動きに似せたいのであれば、差し替える期間を短くしなくてはいけません。

WebのパフォーマンスモデルRAILでは、この動き(Animation)について、約16.67秒で切り替えることを推奨しています。これは一秒間あたり、60回の切り替えが起きる(60fps)ことを意味します。テレビは30fps弱で、ゲームセンターの古い専用機は約50fpsですが、デスクトップPCのディスプレイは約60fpsであり、少なくともコンピューターという枠の中ではデファクト標準です。

ディスプレイ上に何かしらの絵を描画を行っていくうえで、その仕組みは、ゲームであったり業務系のようなアプリであったりと、用途により考え方は異なってきます。エンジニアの方であれば、ダブルバッファリングやら画家アルゴリズムやら、色んな言葉を耳にしたことがあるでしょう。ただこれらは、WebGLであったりCanvasといったディープな技術を使わない限り、隠蔽されていると考えると良いでしょう。

ブラウザは一部の手続きを除いて、基本はシングルスレッドです。最近はパフォーマンス改善により並列化のアプローチが進んでいますが、基本的な部分は変わっていません。その手続は、まるで一本の川のように実行されていきます。⁠JavaScriptの実行」によりDOMの変更があれば、⁠レイアウト」が決定され「ペイント」されます。

ただ、レイアウトやペイントに関係しない処理が多くの時間を奪うと、RAILのI(Idle)やR(Response)に影響が出るため、Chromeブラウザでは描画に関わるタスクを優先させるなどの対策が行われています。実際には一本の川のようにはならないこともあるわけです。なんにせよ、ブラウザはレイアウトを決定してペイント(描画)するというこの一連の流れが起きないことには、ブラウザ上に表示されている内容は変化しません。

では実際に、どのような実現方法があるかについても触れていきましょう。

setTimeout/setIntervalとrequestAnimationFrame(rAF)

最も古典的な手法としては、ブラウザ内のタイマーを使う方法です。代表的なものとしては、setIntarvalなんかを活用して、一秒間に60回のDOM操作を行い、アニメーションを実現するという方法です。この方法では、実際のハードウェアとのリフレッシュレートと同期できないことがあるため、のちのちrequestAnimationFrame(略してrAF)と呼ばれるAPIが考案されました。

古典的なやり方で、CSSのleftを約1秒間で50pxに変える例
var cnt = 0;
function move() {
    cnt ++;
    document.querySelector("hoge").style.left = 50*(cnt/60)+"px";
    if ( cnt < 60 ) {
        setTimeout(move,1000/60); // もしくはrequestAnimationFrame(move)
    }
}

この方法は、古いjQuery/jQuery Mobileのanimateメソッドで活用されていた方法です。animateメソッド自体の呼び出しは一度だけですが、内部的には1/60秒ごとにイベントが実行され、DOM APIを使ってレイアウトを変更し、アニメーションを実現しました。

しかしこの方法、モバイルが主流の時代にはなかなか受け入れられません。

CSS Animation

HTML5がバズワード化していた時代には、CSSでアニメーションが作れるということで非常に注目されました。一言で「CSS3」という呼び方もされたりしました。ただこの仕組み、本当に注目されるべき点は、ハードウェアリソースを効率的に扱えるという点です。

数年前に、モバイルのフレームワークがjQuery MobileからIonic FrameworkやOnsen UIといった、別のアーキテクチャを持つものへと移っていきました。その背景には、jQuery Mobileの持つ旧世代的な仕組み、先ほどにも述べた毎フレームごとにDOMを変更するという効率の悪さが問題となっていたのです。

モバイルはバッテリー消費を抑えるため、あらゆるハードウェアリソースには制限がついています。しかし、CSSの機能の一部には、GPUを活用してレンダリングを提供するものがあります。またCSSによるアニメーションは、各フレームごとにC++をコンパイルして生成したネイティブのコードによって実行されるため、その分高いパフォーマンスが期待できます。

少しサンプルを挙げておきましょう。以下は、hoverに応じてアニメーションするCSSのサンプルです。

CSSで、CSSのleftを1秒間で50pxに変える例
.hoge {
    left: 0px;
    transition: all 1s ease;
}
.hoge:hover {
    left: 50px;
}

上記に加え、transformプロパティを使うとGPUを活用することが多く効率的であるため、モバイル向けフレームワークでは内部的に泥臭い方法で活用されたりもしました。

ただ、CSSによるアニメーションには弱点があります。JavaScriptほど柔軟にはなれないのです。それこそ、アニメーション中に動作を一時停止させるなどの手段を提供するとなると、CSSよりもJSのほうがイベントも豊富で自然に表現できます。そこで新たな流れが生じています。

Web Animation

ここ数年はWebのアニメーションについて、CSSではなくWeb Animationと呼ばれるJavaScriptのAPIによって実現しようという流れになっています。CSS Animationは今後も残り続けますが、SVGのアニメーションを実現する機能であるSMILは、Web Animationへの統合を推しており、Chromeにおいては既に廃止が予定されています。

2014年頃からブラウザへの実装も始まっており、最近のjQueryにおいても、この方法は既に活用されているようです。そもそもですが、インタフェースがjQueryのanimateメソッドと非常に似ており、jQueryに馴染んだデザイナーにも扱いやすそうです。

JavaScriptで、CSSのleftを1秒間で50pxに変える例
// jQuery
$(".hoge").animate({
    left : 50px
}, 1000);


// Web Animation
document.querySelector(".hoge").animate({
    left: 50px
}, 1000);

停止するためのAPIもあります。

document.querySelector(“.hoge”).pause();

今のところまだPolyfillsの活用が必須です。進化の真っ只中にあり、議論もかなり活発に行われているため、過渡期にみられるような仕様の変更と戦わなくてはいけないかもしれません。

連載の最後に。今後のWebについて

計5回の連載、いかがでしたでしょうか。Webのパフォーマンス技術は進化が早いため、筆者自身も記事を書き続けて良いものかと、何度も悩まされました。

例えば、第2回で紹介したsetImmediate APIの代替手段について、requestAnimationFrameが現段階での最善の手段であると紹介しましたが、記事を公開した直後に大きな動きがありました。Googleが旗を振り新しいタスクスケジューリングモデルの開発を始め、非公式なドキュメントを公開し、オンラインミーティングで検討まで始め、現在はではW3Cにて正式に議論し始めているという状況です。

わずか1ヵ月で、第2回の記事は一世代古いドキュメントへと変わってしまったのです。少なくとも2年もすれば、今回の記事のすべてが全く違うものに姿を変えている可能性があるでしょう。しかしその多くは今後、JSライブラリやフレームワークがカバーしてくれることになるため、開発者は意識しなくても良い可能性が高いでしょう。

最後に、今後のWebがどのようになるかについても少し触れておきましょう。

例年通りであれば、2015年10月頃にGoogle主催のChrome Dev Summitが開かれます。Googleはこのイベントに合わせて、機能を全体的にブラッシュアップしていくことでしょう。既に狙ったかのようなタイミングで仕様のアップデートが始まっています。ブラウザ側への実装が待ち遠しいですね。

Microsoftについても、本連載中にEdgeブラウザが正式リリースされ、メジャーバージョンアップの廃止と強制アップデート(一部のエディションを除く)が、公式のものとなりました。Windows 10への入れ替えが進むと、PC上のブラウザにおいてはフラグメントの問題は完全に解消されることになります。PC向けブラウザの未来は明るそうですね。

一方でモバイルについて。GoogleはAdd to homescreenService WorkerNotification APIといった機能を追加することで、モバイル固有のユースケースとのギャップを埋めつつあります。既にFacebookなどの様々なWebサイトが、これらの機能の活用に向けて動き始めています。

また従来、標準ブラウザ/WebViewはAndroid OSのバージョンに強く依存していたのですが、これをやめて、独立してアップデートできるようにしています。Android 5.0以上の端末が普及が進めば、フラグメントの問題も大きく改善されることでしょう。

ただ、AppleではiOSの思想にあわせた機能が優先される傾向にあるため、オープンな場で議論されていることのすべてが、同じモチベーションで動いているとは限りません。iOSは比較的最新にバージョンアップされやすい傾向にあり、Androidのようなフラグメントの問題は起こりにくいのですが、機能面での網羅性はAndroidのブラウザであるChromiumよりもやや劣る傾向にあります。今後はより一層、この問題が大きくなるものとみています。

HTML5というバズワードが失われ、複雑化が進み、以前に比べて直感的に良さが伝わるものというのが少なくなってきたようにみえます。しかし、Webの進化はまったく勢いを落としていません。今もなお、開発者のニーズを埋め続けています。今後も期待していきたいところです。

ここまでお付き合い頂き、ありがとうございました。

おすすめ記事

記事・ニュース一覧