この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
FlashDevelop + Haxe + CreateJS の組み合わせで、ActionScript による Flash 開発のような感覚で canvas を使用したアプリケーション開発が行えることは、前回までで紹介した通りです。しかし FlashDevelop は、HTML や CSS を含めた WEB アプリケーション全体を構築するための機能は備えていません。HTML や CSS を記述することも一応は出来ますが効率は悪いです。
実際の開発では、複雑なロジックを含む機能を Haxe で作成し、それを別のIDEやフレームワークを使ったアプリケーションに組み込むといった作業が発生するはずです。
そこで今回は、Haxe で CreateJS を使用した jQuery Plugin を作成してみます。Haxe で作成した機能を jQuery Plugin 化することで、アプリケーションへの組み込み作業を簡単に出来ます。
jQuery Plugin については、以下の記事を読むとよく分かります。
HTML5 × CSS3 × jQueryを真面目に勉強 ? #8 jQueryプラグインの作り方について詳しく
プロジェクトの準備
プロジェクトを新規作成し、コンパイラー設定でjQueryExternを使用する設定を行います。
jQueryExternのインストールや、コンパイラー設定の細かいやり方に関しては、このシリーズの前々回の記事を参照してください。
jQuery.fn の拡張
jQuery Plugin の実装は、jQuery.fn を拡張して行います。jQueryExtern で jQuery オブジェクトにアクセスするには、JQueryStatic クラスを使用します。JQueryStatic クラスは、jQuery\JQuery.hx 内で定義されているインナークラスなので、いきなりタイプしても自動インポートが上手くいきません。ここに限っては、import 文は自力で記述した方が無難です。
import jQuery.JQuery;
また、JQueryStatic に fn プロパティは定義されていないので、とりあえず Dynamic 型に代入してから fn.extend メソッドを呼び出します。
var jq:Dynamic = JQueryStatic;
jq.fn.extend( {
//・・・処理・・・
});
拡張して追加したメソッド内では、this で DOM 要素を保持した JQuery オブジェクトが取得できますが、そのまま this と記述すると、Haxe コンパイラは this を Main クラスのインスタンスと解釈してしまい、コンパイルエラーになってしまいます。そこで、eval() メソッドを使用して、実行時の this をローカル変数に代入して、以降の処理で使用します。また、メソッドチェーンのために、最後に return しておきます。
var elements:JQuery = Lib.eval("this");
//・・・処理・・・
return elements;
以上の三点を踏まえた、jQuery Plugin のテンプレートです。
package ;
import jQuery.JQuery;
import js.Lib;
class Main {
static function main() {
new Main();
}
public function new() {
var jq:Dynamic = JQueryStatic;
jq.fn.extend( {
yourPluginMethod: function(?options:Dynamic):JQuery {
var elements:JQuery = Lib.eval("this");
//・・・処理・・・
return elements;
}
} );
}
}
Dynamic や eval() を使用しているために少し無理矢理感がありますが、一応これで上手くいきます。
実装サンプル
以下、CreateJS を使ったプラグインのサンプルです。
Main.hx
package ;
import createjs.easeljs.MouseEvent;
import createjs.easeljs.Stage;
import createjs.easeljs.Ticker;
import jQuery.JQuery;
import js.Lib;
class Main {
//エントリポイント
static function main() {
new Main();
}
//ステージ
private var stage:Stage;
//オプション
private var options:Dynamic;
//コンストラクタ
public function new() {
//optionsのデフォルト値
var defaults = {
radius: 5,
alphaDecrement: 0.02,
scaleMagnification: 1.1
}
var jq:Dynamic = JQueryStatic;
jq.fn.extend( {
//rippleメソッドを追加
ripple: function(?options:Dynamic):JQuery {
//デフォルトオプションを引数で上書き
this.options = JQueryStatic.extend({}, defaults, options);
var elements:JQuery = Lib.eval("this");
initStage(elements);
return elements;
}
} );
}
//ステージの初期処理
private function initStage(elements:JQuery):Void {
for (i in 0...elements.length) {
var element:Dynamic = elements[i];
stage = new Stage(cast element);
stage.onMouseUp = stageOnMouseUp;
Ticker.addListener(stage);
Ticker.setFPS(60);
break;
}
}
//MouseUpイベントハンドラ
private function stageOnMouseUp(e:MouseEvent):Void {
//Circleをステージに追加
var circle:Circle = new Circle(options);
circle.x = e.stageX;
circle.y = e.stageY;
stage.addChild(circle);
}
}
Circle.hx
package ; import createjs.easeljs.Container; import createjs.easeljs.Graphics; import createjs.easeljs.Shape;
class Circle extends Shape {
//コンストラクタ public function new(options:Dynamic) { super();
//ランダムな色で円を描く var g:Graphics = graphics; var color:Int = Math.round(16777215 * Math.random()); g.beginFill("#" + StringTools.hex(color)); g.drawCircle(0, 0, options.radius); g.endFill();
onTick = function() { alpha -= options.alphaDecrement; scaleX = scaleY *= options.scaleMagnification; if (alpha <= 0) { cast(parent, Container).removeChild(this); } } } } [/as3]
ripple.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>HaxeJQPluginSample</title>
<meta name="description" content="" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>
<script src="jquery.ripple.js"></script>
<script type="text/javascript">
$(function() {
$('#canvas').ripple({radius: 10});
});
</script>
</head>
<body>
<p>キャンバスをクリック!</p>
<canvas id="canvas" width="400" height="400" style="background-color:#EEE"></canvas>
</body>
</html>
実行結果
非常に簡潔な記述で、HTMLへ組み込む事ができました。通常のHTMLとCreateJSを使用する箇所で分業を行う場合など、このようなやり方で進めれば、スムーズに行くと思います。