Haxe/JS: 非同期イベント監視に enum を使用: ブラウザにドラッグ&ドロップで画像を表示するサンプル
Haxe の enum 用途例です。
JavaScript ターゲット出力で、ブラウザにドラッグ&ドロップで画像を表示するサンプルを元に解説します。
資料
html への ドラッグ&ドロップで画像を表示する方法は、以下のサイトに解説があります。
JavaScript で File API を使用してファイルを読み取る
http://www.html5rocks.com/ja/tutorials/file/dndfiles/
上記内容を Haxe でもろもろアレンジした内容のソースコード一式は以下に配置しました。外部ライブラリには jQueryExtern を利用しています。
https://github.com/siratama/DragAndDropImageSample
動作サンプルは以下となります。画像ドラッグ&ドロップで表示。画像ファイル以外は alert が表示されます。
http://www.dango-itimi.com/blog/swf/215/
ドラッグ&ドロップするファイルはローカル PC 上で解析・表示が行われます。サーバにアップロードされるわけではないので適当なファイルを放り込んでも大丈夫です。
要所解説
メイン処理となる DragAndDropSample クラス の各所を切り取っての解説です。
初期設定
private function initialize() { dropZone = new DropZone(); imageFileReader = new ImageFileReader(); imageViewer = new ImageViewer(); mainFunction = observeDropZone; timer = new Timer(100); timer.run = run; } private function run() { mainFunction(); }
initialize メソッドでは、各インスタンスの生成と監視用タイマーの設定を行っています。
各クラスは以下の役割があります。
DropZone --- ドラッグ&ドロップ範囲の定義とドラッグ&ドロップされたファイルの探知 ImageFileReader --- ドラッグ&ドロップされた画像ファイル読み込み ImageViewer --- 読み込まれた画像ファイルを表示
mainFunction は Void->Void のメソッド型です。run メソッドにより mainFunction に設定されたメソッドが 定間隔で実行されます。
ドラッグ&ドロップの監視
private function observeDropZone() { var event = dropZone.getEvent(); switch(event) { case DropZoneEvent.NONE: return; case DropZoneEvent.DROP_FILE_ERROR(message): js.Lib.alert(message); case DropZoneEvent.DROPPED(file): initializeToReadImageFile(file); } }
observeDropZone は一定間隔ごとに run メソッドから実行されます。 DropZone.getEvent メソッドから event インスタンスを取得する事で、次の行動へ移行するかの判断を行います。 event は 以下の enum インスタンスとなります。
enum DropZoneEvent { NONE; DROP_FILE_ERROR(message:String); DROPPED(file:File); }
enum を受け取ることにより、何が起こったかの判断と、それぞれ起こったことに対するデータの取得が一括で行える点がポイントとなります。
ファイル読み込み・表示
ドラッグ&ドロップされたファイルを読み込み表示するまでの処理です。mainFunction の内容を observeToReadImageFile メソッドに変更する事で、次は observeToReadImageFile メソッドが定間隔で実行されるようになります。
private function initializeToReadImageFile(file:File) { imageFileReader.start(file); mainFunction = observeToReadImageFile; } private function observeToReadImageFile() { var event = imageFileReader.getEvent(); switch(event) { case ImageFileReaderEvent.NONE: return; case ImageFileReaderEvent.READ(data): imageViewer.show(data); mainFunction = observeDropZone; } }
先ほどと同じように、ImageFileReader.getEvent メソッドから event を取得する事で、次の行動に移行するかの判断を行います。event インスタンスは以下の enum 定義となっています。
enum ImageFileReaderEvent { NONE; READ(data:String); }
何も読み込みが行われていない場合は NONE、読み込みが行われたら READ にそのデータが設定される、というシンプルな内容です。読み込みが行われた/行われなかったの正否判断(Bool相当)と、読み込みが行われたファイルのデータの取得が 一つとして扱える点がポイントとなります。
まとめ
ドラッグ&ドロップ・ファイル読み込み どちらも非同期処理となります。処理が終了するまでの状況をを監視し、状況を enum インスタンスで返却することで、とてもすっきりした処理作成が可能となります。