JS AS / Shibuya.js in Kyoto
本日の OSC Kansaia 2008 で開かれた Shibuya.js in Kyoto で、JavaScript と ActionScript の連携について話しました。関西のカンファレンスでの発表は初めてでしたが、楽しかったです。スピーカの皆さん、参加された皆さん、どうもありがとうございましたー。
以下発表資料です。
JS <-> AS
- JavaScript と ActionScript の連携
自己紹介
- はてなエンジニア
- 舘野 祐一 (id:secondlife)
- Ruby, ActionScript3, JavaScript
JS と AS
- JS だけでよくない?
- AS だけでよくない?
- 相互に補完しあえる関係
- 両方使えると、様々なメリットが
JavaScript -> ActionScript
- crossdomain.xml, domain 超え
- ファイルの複数選択による同時アップロード
- swfupload ( http://swfupload.org/ )
- バイナリ操作
JavaScript -> ActionScript
- マルチメディア関連
- ふんだんなFlashPlayerAPI
- html 画像のリアルタイム加工
- アンチエイリアスフォントで描画
- AS ライブラリの利用
- 画像情報取得(exif, 色情報... etc)
- 音楽再生(FlMML ... etc)
ActionScript -> JavaScript
- URL の変更
- location.query, location.hash
- JS の API での情報取得
- navigator.userAgent
ActionScript -> JavaScript
- html の要素取得
- ブログパーツ等で、ブログの本文等の情報利用
- html 上に動的オーバーレイ, スクロール制御
JS <-> AS の API
- ExternalInterface
- ExternalInterface#addCallback
- JavaScript から呼び出せる API を登録
- ExternalInterface#call
- JavaScript を呼び出す
- ExternalInterface#addCallback
ExternalInterface# addCallback
JS 側から
$('flash_id').example(arg);
で簡単に呼び出せる!けど問題が…
- 関数呼び出し時、swf がロードし終わってないとエラー
- Flash 側での非同期処理
- JS にどうやって通知するか
swf 未ロード問題
- swf ロード完了時に、ExternalInterface#call で JS 側に通知
MyApp.onLoad = function() {
MyApp.example(arg);
};
// AS 内部でロードが終わったら通知
ExternalInterface.
call('MyApp.onLoad');
Flash 側での非同期処理
- ネットワーク上のファイルをロードし終わったら、等の処理
- Flash 側の非同期処理完了時、ユニークなIDで関数を呼ぶ
// AS 処理完了時
ExternalInterface.
call('MyApp.exampleCallback', uniq_id, data);
- 通常は JS 側で Object を作って処理をラップ
- 使いやすい API に
ExternalInterface#call
- JavaScript の関数呼び出し
ExternalInterface.
call('MyApp.exampleCallback', uniq_id, data);
ExternalInterface#call 問題点
-
- 'Foo.bar.baz' な関数のみ
- 'Foo.bar().baz' などの呼び出しは不可
- JS の変数への代入、参照も不可
- ExternalInterface. call('document.body.innerHTML'); // エラー
- 'Foo.bar.baz' な関数のみ
ExternalInterface#call
クロージャな文字列で渡すと何でも可能
# JS の変数の参照
var body:String = ExternalInterface.call('(function() { return document.body.innerHTML; })');
# JS の変数へ代入
ExternalInterface.call('(function(arg) { document.body.innerHTML = arg; })', 'hello');
ExternalInterface#call BK その他
- その他 JS 呼び出しの BK がいろいろ
- http://github.com/hotchpotch/as3rails2u/tree/master/src/com/rails2u/utils/JSUtil.as
ExternalInterface#call
複雑な呼び出しになると大変
- そこで…
JSProxy
ExternalInterface#call の面倒な処理をよしなにしてくれる
var body:String =
JSProxy.proxy.document.body.$innerHTML;
JSProxy.proxy.document.body.$innerHTML
= 'hello';
JSProxy - Example
var location:JSProxy = JSProxy.proxy.location;
// location の情報を取得できる
var browserUrl:String = location.$href;
var hostname:String = location.$hostname;
location.$href = 'http://www.hatena.ne.jp/';
JSProxy - HTML フォームの送信
var form:JSProxy =
JSProxy.proxy.document.
getElementById('testform');
var inputs:JSProxy =
form.getElementsByTagName('input');
inputs[0].value = 'oreore';
inputs[1].value = 'oreore@example.com';
form.forceAsync = true;
form.$submit();
JSProxy
- 続きは Web で!
- JSProxy を使うと AS -> JS は楽に
- JS -> AS を楽にしたい
Uffy
- http://github.com/hotchpotch/uffy/tree/master
- AS から簡単に JS のクラス作成・メソッド定義
- 今まではラッパをいちいち書いていた
- Uffy を使うと、独自ラッパ定義しなくておk
Uffy.as
import uffy.javascript;
public class URI {
javascript function getURL(...)
javascript function postURL(...)
import uffy.Uffy;
Uffy.register('URI', URI);
Uffy.js
var uffy = new Uffy('GetURL.swf');
uffy.load('URI', function(URI) {
var uri = new URI;
uri.getURL(fooUrl, callbackFunc);
});
// 別のを register してやるとそいつも
uffy.load('Exif', function(Exif) {
var uri = new Exif(url);
exif.load(callbackFunc);
});
no Uffy.js
JS 側は Uffy.js 使わなくても OK
var uri = new $('my_swf_id').URI;
uri.getURL(fooUrl, callbackFunc);
var exif = new $('my_swf_id').Exif(url);
exif.load(callbackFunc);
Uffy help
- 自動で help 変数が登録される
alert($('my_swf_id').UffyTest.help);
- help 変数は、定義された関数の引数や戻り値を表示
callFunc(**, Function):**
refrect():**
foo():String
Uffy
- 1swf の id に複数の JS のクラスが持てる
- javascript namespace による関数登録
- AS 側は、AS のクラスを書くように JS のクラスを定義
- help の表示
- Uffy.js を使った swf ロード待ち
- その他…
まとめ
- JS <-> AS は相互に補完しあえる関係
- AS でできないブラウザ操作を JS 経由で
- JSProxy 使うと便利!
- JS でできないこと、難しいことを AS に
- Uffy 使うと便利!