読者です 読者をやめる 読者になる 読者になる

Adobe AIR 2.0 airhttpd でサーバ側でロードした swf のフレームショットをHTML5対応ブラウザで簡易アニメ表示させてみた

Adobe AIR Flex

なんか airhttpd を使って面白いものを作れないかと思い、SWFLoader を使って外部 swf ファイルをロードし、そのフレームのスナップショットをHTTPクライアントに返すサーバーアプリを思いついた。

HTML 5 の Canvas 対応をブラウザであればそれを JavaScript で描画していくことができる。

開発環境とライブラリ

ファイル構成

 lib/
     airhttpd-0.5.swc
 src/
     docroot/
        index.html
     webapp/
        CGIService.as
     Main.mxml

CGI処理

airhttpd の FileService クラスを継承して CGIService クラスを作ります。

package webapp {
  import com.tilfin.airthttpd.server.HttpRequest;
  import com.tilfin.airthttpd.server.HttpResponse;
  import com.tilfin.airthttpd.services.FileService;
  
  import flash.filesystem.File;

  public class CGIService extends FileService {
    
    private var _snapShotFunc:Function;

    public function CGIService(snapShotFunc:Function, docroot:File) {
      super(docroot);

      _snapShotFunc = snapShotFunc;
    }

    override public function doService(request:HttpRequest, response:HttpResponse):void {
      if (request.path == "/action") {
        response.contentType = "image/png";
        response.body = _snapShotFunc();
        return;
      }

      super.doService(request, response);
    }
  }
}

/action のリクエストが来たらコンストラクタで指定された snapShotFunc を呼び出して png の画像バイト配列を返す。

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
  <mx:Script>
    <![CDATA[
      import com.tilfin.airthttpd.server.HttpListener;
      import webapp.CGIService;
      import mx.graphics.codec.PNGEncoder;
      
      private var _pngEncoder:PNGEncoder;
      private var _listener:HttpListener;

      public function init():void {
        _pngEncoder = new PNGEncoder();

        _listener = new HttpListener(function(line:String):void {
            trace(line)
          });
        _listener.service = new CGIService(getSnapShot,
              new File(File.applicationDirectory.nativePath + "/docroot"));
        _listener.listen(9080);
      }

      private function getSnapShot():ByteArray {
        var bmpdat:BitmapData = new BitmapData(150, 200, false);
        bmpdat.draw(loader.content);
        return _pngEncoder.encode(bmpdat);
      }
    ]]>
  </mx:Script>
  <mx:SWFLoader id="loader" width="150" height="200" opaqueBackground="0xffffff" cacheAsBitmap="true"
          source="SWFファイルのURL"/>
</mx:WindowedApplication>

SWFLoader を一つ配置して、そのスクリーンショットを撮る getSnapShot を用意する。そのメソッドを CGIService に渡して HttpListener のサービスとしてセットする。
creationCompleteで以上を行い、サーバーを起動する。

index.html

ブラウザで表示する HTML 5 の HTMLファイル。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
var canvasContext;
var imageCache;

function init(){
  imageCache = document.getElementById('image');
  imageCache.onload = image_onload;
  canvasContext = document.getElementById('canvas').getContext('2d');
  setInterval(timer, 200);
}

function timer(){
  imageCache.src = "/action?dm=" + new Date().getTime();
}

function image_onload(evt){
  canvasContext.drawImage(imageCache, 0, 0);
}
</script>
<title>Flash Viewer</title>
</head>
<body onload="init()">
<canvas id="canvas" width="150" height="200"></canvas>
<img id="image" width="150" height="200" style="display:none"/>
</body>
</html>

timerで0.2秒おきにサーバーへ画像(スクリーンショット)を取得しに行く。いったん非表示のimageにロードし、ロード完了イベントで canvas のコンテキストに対して描画する(drawImage) 。

結果


こんな感じ iPod touchSafarihttp://AIRのサーバホスト:9080/ にアクセスするとパラパラ漫画のように Flash のアニメーションが表示される。

テストに使わせてもらった Flash は Afternoon Tea|Blog Parts|アフタヌーンティーの季節のテーマをモチーフにしたブログパーツ(無料)