Flashの代替としてのHTML5 | サイバーエージェント 公式エンジニアブログ
はじめまして。Morino(@kohei_april20)と申します。
私は入社して以来、仮想空間サービスのアメーバピグやFacebookアプリの開発などFlashベースのプロジェクトに主に関わって来ましたが(どちらかというとサーバサイドでしたが)、9月より異動になり、既存のFlashコンテンツベースのサービスのスマートフォン対応を担当することになりました。周知の通りiOS(iPhone、iPad)でFlashはサポートされず、ブラウザ上で動かすのであればHTML5関連の技術を使って何とかしなければなりません。Flash的な「タイムラインによるベクターアニメーションを使うアプリケーション」を、既存のSWF素材を活用しつつ、また確立された開発体制をなるべく崩すこと無く、スマートフォンのブラウザ環境でのHTML5においていかに実現するかが目下の課題といったところです。
さて、世間的にも、FlashでできることはHTML5でできるという主張のもと「Flash vs. HTML5」という構図が作られてしまっているのも加勢して、HTML5にFlash的なクオリティを求められることが増してきているように感じます。しかし、この2つの技術は生い立ちも特徴もかなり異なるもので、単純に置き換えるという簡単な話ではなく、自分を含め頭を悩ませる人も多いのではないでしょうか。
ということで、私自身が取り組み始めてまだ日は浅いですが、ここ最近調査・検証したことを通して、「Flashの代替としてHTML5」というものどのように実現していけば良いのかということについて考えを述べたいと思います。

API的には確かに代替可能

少なくともAPIを見るかぎりでは、確かにHTML5はFlash的なこと(タイムラインによるベクターアニメーションを使うアプリケーション)が実現可能なものが揃っています。Flashアプリケーションの要素を大きく3つに分けるとすると、以下のようにHTML5では実現できるはずです。
  • ベクター画像→canvasタグやSVGによる描画
  • アニメーション→canvasの再描画やCSSアニメーション
  • スクリプトによるロジック→JavaScript
  • ※canvasは描画後ラスターになってしまうのでスケール後は再描画する
とは言っても、例えば画像を描画するにもAPIが「ここからここまで線を引く」など低レイヤーなものしかありませんし、ちょっとでも複雑なアニメーションを作るならオーサリングツールは必須でしょう。
Flashの開発の場合、これら3つの要素は一般的に次のようなツールによって作成されると思います。
  • ベクター画像→Adobe Illustratorなどのベクター画像のドローソフト
  • アニメーション→Adobe Flash(画像はインポートしてアニメーションをつける)
  • スクリプトによるロジック→Flash Builder(もしくは他のエディタ)
このようにFlashの場合は開発のスタンダードなやり方がある程度確立しているので、とてもわかりやすいです。ベクター画像はShapeオブジェクトとして、アニメーションはMovieClipオブジェクトとして扱え、マウスイベントなどにも対応していて簡単に扱えます。
ところがHTML5においてはFlashのようなスタイルでのスタンダードな開発手法は今のところ存在しないのではないでしょうか。そもそもFlashの開発スタイルを丸々コピーすべきでもないのかもしれません。
しかし、万能を求めるのは難しいけれどもいろいろな側面から開発の助けとなりそうなライブラリやツールは利用可能なので、まずそれらについて紹介します。

Flash的なHTML5の実装

Flash的なアプリケーションをHTML5で実装するアプローチは次の2つのどちらかが現実的ではないかと思います。
  • JavaScriptからオブジェクトとしてアクセス可能なベクター画像やアニメーションを、素材として作成できるフローを確立し、ロジックをJavaScriptで実装する
  • アプリケーションは完全にFlashとして作ってしまい、それをまるごとコンバートする
そこで、ベクター画像やアニメーションを利用可能な素材として作成するのに役立つものや、SWFごと変換するコンバータなどを以下に紹介します。

ベクター画像

複雑なアニメーションを必要としない、もしくは何かアニメーションをつける方法が別に用意できるような、ベクター画像を抽出するだけで良い場合の手法です。
ベクター画像ドローツールでSVG形式でデータを作成する
SVG形式であればHTML5でベクター画像を扱えます。しかしAndroidのブラウザは現状SVGに対応していないので表示できません。
Ai->Canvas
Adobe Illustratorのプラグインで、ベクター画像をcanvasへの描画コードとして出力できます。
swfから抽出する
アニメーションと共にSWFデータから抽出します。アニメーションの抽出に関しては後述します。
(ベクターを諦めてラスターにしてしまう)
アプリケーションにおいて画像を大きくスケールさせる必要がなく、ラスター画像で十分という場合はベクター画像に固執せずにシェイプをラスター画像として用意するのも手です。

アニメーション

オーサリングツールを使うことを前提として、アニメーションを実現するためのツールを紹介します。
Sencha Animator
CSSアニメーションをタイムラインベースで作成できるオーサリングツールです。サンプルの出力結果を見ると、各要素がid付きのdiv要素になっているのでJavaScriptからロジックを付け足すのもやりやすそうな印象でした。ベクター画像にはまだ対応していないようです。
Adobe Edge Preview
まだプレビューリリースですが、Adobe公式のオーサリングツールで、Adobe FlashのHTML5/CSS3/JavaScript版という感じです。ベクター画像はSVGで出力されます。出力されたスクリプトはminifyされているのであまり詳しくは分かりませんでしたが、アニメーションはJavaScriptによりフレーム毎にDOM要素にアクセスしてスタイルを書き換えて変形などの操作をしているようです。
EaselJS
EaselJSは、ActionScriptに似たAPIでcanvasの描画を行うライブラリで、canvasの再描画によるアニメーションが作成できます。アニメーションデータは別途用意されているZoë(http://easeljs.com/zoe.html)というSWFアニメーションエクスポーターを利用することでAdobe Flashで作成したアニメーションを抽出することができます。ただし、ラスター画像のスプライトシート(パラパラ漫画のコマを一枚の画像に並べてまとめたようなもの)を作成してこれを再生する方式しか今のところ用意されていません。
また、canvasの再描画はコストが高いですが、それを補うキャッシュの仕組みも用意されているようです。(検証をしているサイト:http://banners.aquafadas.com/yann/testWebkit/EaselJS_v0_3_2/examples/cache.html
google swiffy
SWFのHTML5コンバータです。画像とアニメーションを抜き出すだけでなくActionScriptの動作までまるごとコンバートできるコンバータはかなり発展途上で、swiffyも今のところ対応しているのはSWF 8 and ActionScript 2.0のサブセットまでです。SWFをウェブのUIからアップロードして出力結果を得るインターフェースで、出力結果はminifyされていて手を加えるような余地もないので、利用できるケースは限定されますが、再現度はかなり高いようです。画像はSVGのようです。
Adobe Wallaby
こちらはAdobe製のコンバータです。出力結果の例がこちらで解説されていました。(http://yoo-s.com/topic/detail/322)-webkit-keyframesを使ってCSSでアニメーションを書きだしています。画像はSVGです。minifyされていないので、手を加えたり切り出したりするのは比較的し易いと思います。
FlashForward
FlashLite1.1のコンバータです。中間コードを介してパーサとランタイムが独立していて、出力を動的するという応用も可能です。画像はSVGとcanvasを選択可能で、アニメーションはSVGの場合フレームごとのDOM要素操作、canvasの場合は再描画で実装されているようです。
もしくは、SWFを自前でパースする
SWFをパースしてHTML5で表現する技術をいくつか見てきましたが、現状はどれも一長一短である上まだまだ発展途上なものばかりであると言わざるを得ません。これらを用いて要求を満たせればラッキーですが、そうでない場合自前でパースするしかありません。SWFの仕様はAdobeにより公開されています。(http://www.adobe.com/devnet/swf.html)これに基づいてパーサを作成して必要なデータを抽出します。SWFのデータはかなり最適化が図られており、場所によってはビット単位でデータを読んだりする必要がありますが、パースして扱いやすいオブジェクトに詰め込んでくれるようなライブラリも幾つかあるので、それを利用するのも手です。JavaであればTransform SWF for Java(http://www.flagstonesoftware.com/transform/)などがあります。ライブラリを使わずに自前でバイナリを読んでいく場合は、ソースの見ることのできるFlashForwardやオープンソースのFlash Playerであるgnash(http://www.gnu.org/s/gnash/)、JavaScriptで実装されたflash player(swf1とswf2の一部のみ対応)であるgordon(https://github.com/tobeytailor/gordon/wiki/)などが参考になるのではないでしょうか。また、GREE Engineers' Blogの「バイナリ編集のススメ」シリーズ(http://labs.gree.jp/blog/2010/08/631/)ではSWFデータの構造について解説されていて参考になると思います。

グラフィカル/インタラクティブなアプリのフレームワーク

本エントリでは主に画像やアニメーションの導入について触れていますが、グラフィカル/インタラクティブなアプリケーションを作成するためのフレームワークも簡単に紹介します。
LimeJS
ネイティブアプリ的なリッチなUIのアプリケーションをHTML5関連技術で実現するためのフレームワークです。APIドキュメントを見てみた限りでは、結構高機能そうな印象でした。
cocos2d-javascript
cocos2dはiOS用アプリ作成のフレームワークもありますが、それのHTML5 canvas版です。Box2Dという剛体の運動の物理シミュレーションの機能があります。

実験

既存のFlashコンテンツベースのサービスのスマートフォン対応するにあたって、私が今回実現したいのは次のものです。
  1. 既存システムがSWFを動的に生成するので、それを元に動的にHTML5を出力したい
  2. iOSとAndroid両方に対応したい
  3. 変換後のコードに対して、スマートフォン向けUIとしてHTML5用に手を加えられるようにしたい
実験1 Transform For Java + EaselJS
まず1の動的に使えるという条件を満たすにはFlashForwardくらいしかなかったのですが、FlashForwardは実装がPHPのウェブアプリケーション的で、独立して使いづらかったのと、中間データがファイルに書き出されるので運用時のI/Oが心配だったので、パースはTransform For Javaを使って自前で実装してみることにしました。
そして2を満たすために画像はcanvasベース、3を満たすためにJavaScriptとして素材にアクセスしやすそうということでEaselJSを採用しました。EaselJSにはベクター画像のアニメーションを扱うMovieClip的なものがなかったのでそこだけ自前で実装しました。
とりあえず基本的なシェイプだけ描画してアニメーションを付けてみるということをしたのですが、実機での動作が遅く実用には向きそうにありませんでした。特にiPhone4で試したときは、ディスプレイの解像度が高いのでその分canvasの再描画のコストが高くなっている印象でした。
実験2 アニメーションをCSSに
canvas再描画方式は諦めて、アニメーション部分をkeyframesを使ったCSSアニメーションで書き換えることにしました。画像は同じくcanvasで描画しますが、一枚のcanvasに描画するのではなく、div要素で階層的にcanvas要素を構成し、そのdiv要素に変形などの操作をするように変更しました。EaselJSはもはや必要なかったので、API設計を参考にしつつ、JavaScript部分は自前で実装することにしました。なお、CSSアニメーションであればiOSでGPUアクセラレーションが効くのでなめらかなアニメーションが期待できます。(アクセラレーションが効いているかどうかをiPhoneシミュレータで確認する方法が紹介されています:http://hazumu.net/blog/2011/02/24/css3でiosのアクセラレーターを使う/)そしてその結果、なんとか実用に耐えそうなレベルでのアニメーションを作成することができました。今後これをベースにSWF->HTML5コンバータの作成を進めていこうと思っています。

終わりに

いろいろ検討した結果、結局SWFを自前でコンバートすることになってしまいました。ちなみにGREEさんではReel、DeNAさんではExGameというSWFの変換エンジンを自社で持っているようです。今後、もっと利用可能なライブラリやツールが充実し、スマートフォンのハードウェア及びブラウザの性能も向上して今の厳しい制約条件も緩和してくることを期待したいですが、HTML5で(特にスマートフォン向け)のFlash的なウェブアプリを開発するとなると、Flashの開発と比べて多くのハードルの乗り越えなければならないのが現状のようです。