LoaderContext/ApplicationDomainの使い方を自分なりにメモ

未だによく分かってないのでメモ。

swfが親子になっていて、それらのクラスを共有させたい場合、これを使わないと、エラーが出て何が何だか分からなくなる。あと、音ファイルだけ別にしてgetDefinitionByNameする時とか。

基本は親と子で同じクラスを使いたいと思うので、親が子を読む際に自分と同じApplicationDomainに読み込む。

var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;

loader.load(path, context);

通常はApplicationDomain.currentDomainを使っていれば問題ないみたいなんですが、子供同士でバッティングしてしまうクラスがあると面倒なことになる様子。

この場合は

context.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);

として子供のcontextを逐次変更すれば、子供同士のクラスはバッティングしなくなりながらも、子供は親と共通のクラスを使える。はず。

何でもApplicationDomain.currentDomainにすればいいってもんでもないんですね。

loaderInfoからapplicationDomainを取る方法もあるみたいですが、勉強不足。

参考

そろそろTweensyを覚えたい。

テキスト入力の備忘録

随分久々になってしまいましたが、そろそろこちらを有効活用しようかなと思い始めています。

さて、Flashを使っているとブラウザやプレイヤーによってさまざまなバグと遭遇することがありますが、前に痛い目を見たのが「テキスト入力」。プレイヤーが一緒でもブラウザによって動作が違うなど、なかなか曲者です。

FileReferernceとテキスト入力

最も悩まされたのがこれ。IE7+Windowsで発生。FileReferenceでファイルをアップロードして文字情報を入力するようなものだったんですが、FileReference.browse()を実行した後、半角全角キーが効かなくなり、半角英数しか入力できなくなるという現象がありました。一度Flashからフォーカスを外せば治る(例えば検索バーにフォーカスを当てるとか)のですが、まあ、それを利用者に強要するわけにもいかない。さてどうしたものか。

結局、FileReferenceにイベントリスナをつけて、ファイルが選択された、あるいはファイルの選択がキャンセルされた時に、Flashへのフォーカスを当てなおせばいいようです。

これ、アップロードする部分と文字情報入力部分が離れてたもんで、危うく気づかないところでした。

private function windowActive():void{
  if(Capabilities.os.substr(0, 3) != 'Win'){return;}
  try{
    ExternalInterface.call('function(){window.focus();document.getElementById("FlashのID").focus();}');
  }
  catch(err:Error){
    trace(err.message);
  }
}

try-catchしないとFlashIDEでデバッグした時にエラーになってしまうので一応。

Mac Leopard+Firefox3

上記の対策で、さてWindowsは動いたよかったよかったと思ってたんですが、今度は逆にMac LeopardのFirefox3で動かなくなってしまいました。仕方ないので、OS判定を入れることにしました。原因はそこにあったか不明ですが、とりあえずWin,Macともに動くようになりました。

Firefox2やSafari3では問題なかったのでMacというよりMac版Firefox3の問題だとは思いますが、何故起こったのか未だにわかりません。特に問題のあるコードでもなさそうなんですが。

Mac Tigerでの不具合

日本語の入力モードの変換にはIME.enabledのtruefalseやIME.conversionModeの切替で行いますが、IME.conversionModeが実は曲者だったようで、Mac Tiger環境下でJAPANESE_HIRAGANAに変更すると時々ブラウザごと落ちる場合がありました。実際には変更した瞬間ではなく、モードを変更し、違うフィールドに移った上で、2回以上変換キーを押すと落ちるという感じした。

  1. 日本語入力フィールドが2つあって、それぞれ、フォーカスが当たったらconversionModeを変更するようにした。
  2. 一方のフィールドにフォーカスが当たっているだけのときはいくら変換キーを押しても問題なし。
  3. しかしその後、他方のフィールドにフォーカスを当て、日本語を入力し、変換キーを押すと2回目でブラウザが落ちる

これはブラウザに関係なく、Mac Tiger環境では全てそうなりました。まあ、何かしらやり方が不味かったのかもしれませんが。とりあえず、IME.enabledの変更は効くようなので、そちらに逃げることでブラウザ強制終了は回避できるかと。自動で日本語入力にはできないことになりますが、落ちるよりはマシかなーとね。

もしかすると、TextFieldのrestrict設定の有無でも動作が変わるかもしれません。この辺りは要調査かな。

JSFLに触れてみる

前回FuseKitについて書きつつも何故かタイムラインでの作業をしていたら、いろいろ面倒なことがあることに気づいた。タイムラインベースで作成していると直感的にオブジェを置いたり動かしたりできるのはいい。でも中心点が真ん中になってないとか、画像の座標に小数点以下が含まれてて画像がぼけるとかでちょっと面倒な作業ができてしまう。

作ってる時は面倒だなぁと思うだけだったんですが、それを作り終わってさてどうしようとなった時に、「そうだ、JSFLってものがあるじゃないか」と思い当たったので、勉強がてら作成してみました。

最初はとっつきにくいと思ったんですが、ActionScript,JavaScriptがある程度分かれば、少しのサンプルと公式ドキュメントがあれば、ある程度のことはできそうです。

とりあえず、上記サイトさんを参考に、動きとしてはほぼ同じですが、ステージ上のオブジェクトの座標を四捨五入して配置しなおすものを作成してみた。

/**
 * ステージ上に配置されたオブジェクトの座標の小数点以下を四捨五入するjsfl
 */
var doc = fl.getDocumentDOM();

var aryLayers = doc.getTimeline().layers;
//各レイヤー
for(var i = 0; i < aryLayers.length; i++){
    var aryFrames = aryLayers[i].frames;
    //各フレーム
    for(var j = 0; j < aryFrames.length; j++){
        //キーフレームでなければ次へ
        if(j != aryFrames[j].startFrame){continue;}
        //各エレメント
        var aryElements = aryFrames[j].elements;
        for(var k = 0; k < aryElements.length; k++){
            var elem = aryElements[k];
            //インスタンスの場合
            if(elem.elementType == 'instance'){
                var mat = elem.matrix;
                mat.tx = Math.round(mat.tx);
                mat.ty = Math.round(mat.ty);
                elem.matrix = mat;
            }
            //シェイプの場合は頂点を移動
            else if(elem.elementType == 'shape'){
                elem.beginEdit();
                var aryVertices = elem.vertices;
                for(var l = 0; l < aryVertices.length; l++){
                    var vtx = aryVertices[l];
                    var posX = Math.round(vtx.x);
                    var posY = Math.round(vtx.y);
                    vtx.setLocation(posX, posY);
                }
                elem.endEdit();
            }
        }
    }
}

シェイプの時は無理矢理頂点を取って、四捨五入してみたら一応移動はしました。シェイプの元の大きさが変わってしまう場合があるので、使う方がいたら注意してください。

利用方法は、こちらを参考に。

普通は上記Configuration内にあるCommandsに入れるようです。付けたファイル名がそのままFlashIDEの「コマンド」のところに出ます。

今更ながらFuseKitを試す

1年以上ぶりながら、本家にこういうことを書くのもどうかと思ったのでとりあえずこちらにメモ。普段AS3を勉強してはいるんですが、仕事上どうしてもAS2でなければならないものも多くあり、やっぱりAS2にも慣れておかないとなということで、AS2でアニメーションするときのための便利なライブラリとしてFuseKitを学習しようというお話です。

参考

FuseKitを試すのだ! (1)〜

勉強になります。

インストール

MosesSupposes :: Fuse Kit

まずは上記リンクから一式DLしました。落としてきたzipファイルのcomから下を適当にフォルダに入れてFlashの設定からパスを通せばいい模様。

使う

import com.mosesSupposes.fuse.*;
ZigoEngine.simpleSetup(Shortcuts, PennerEasing);

test_mc._brightness = 100;
test_mc.tween("_brightness", 0, 1, "easeOutBack", 1);

という風に書いて、黒い四角だけ描いたムービークリップにtest_mcとつけてプレビューしたら、白い四角がtweenしつつ黒い四角になるものが完成。お次は複数tweenをする場合を見ていけばいいかな。

JSONP + PHP

 えらく久しぶりになってしまったなぁ。

 JSONPを勉強して、DSでAjaxっぽい通信ができないものかと考えていたのですが、JSONPの解説された本というのはないらしくWeb上の記事で何とかするしかなかった。しかしどれを見てもピンと来ませんでした。

 TAGGYのサンプルが一番役に立った気がします。とりあえず打ち込む前に印刷して読んでいたら何となく雰囲気はつかめました。が、別のことをやっていてかなり放置していました。今日実際に打ち込んで改変してみたら動作はあっさり分かりました。やっぱりサンプルがあるといいですね。以下自分の作ってみたもの。

 クライアント

<script type="text/javascript">
function jsonptest(data){
  alert(data.p);
}
function test() {
  scriptTag = document.createElement("script");
  scriptTag.type = "text/javascript";
  scriptTag.src = "./jsonp.php?p=1&id=123";
  document.getElementById('abc').appendChild(scriptTag);
}
</script>
<input type="button" value="実行" onclick="test()">
<div id="abc">
</div>

 サーバ

<?php
$p = htmlspecialchars($_GET['p']);
$id = htmlspecialchars($_GET['id']);
echo <<<JSONP
jsonptest({
  "p" : "$p",
  "id" : "$id"
});
JSONP;
?>

 こんなんでいいのかな?と思いながら動かしたんですが普通にOKでした。これでPHPでの処理を加えればデータの送信もできそう。まだローカルで実験しただけですが、サーバ間通信もできると思います。多分。

 ・・・本当はこれすんなり動いたわけではなくて、まずTAGGYのサンプルを見ずに作って、これで大丈夫だろう!というのが動かず、TAGGYにサンプルあったなぁというのを思い出し、それをコピーしてみて動作を確認して、それを改変したら動きました。しかし、元のサンプルを見ずに作ったものがマネしようと何しようとどうやっても動かず、「何が問題なんだーーー!!」と思っていたら、

 「script」が「srcipt」になってました。

 ああ、何という時間の無駄。

document.documentElement.clientHeightの挙動

 まあ、メモ代わりに。

 javascriptはブラウザによって挙動が異なるものだから困る。こないだはKonquerorというブラウザだけうまく動作しないと思ったら、KonquerorさんはJavaScriptを外部scriptにした場合、必ずUTF-8として読み込むらしく、Shift_JISで書いたらうまく動作しなかった。もちろん日本語含んでなければ動作するんでしょうけど。結局それは全てをUTF-8にしたらうまくいきました。

 今回はSafariでの謎。Macは普段は使わない(持ってない)ので動作確認の時に使うくらいなんですが、あまり熱心に確認してなかったため、気づかない問題があった。それがdocument.documentElement.clientHeightの挙動。

 window.innerHeightとほぼ同じ値をとるか、あるいはundefinedかと思っていたんですが、両方alertしてみたらwindow.innerHeightはちゃんと高さが表示されるものの、document.documentElement.clientHeightはなぜか中途半端な数値がでてきました。

 これを使って条件わけしていたので謎の挙動をしていたわけで、条件文を変えたらあっさり直りました。widthのほうはどちらも同じ値になってたんですが、なぜheightだけそうなるんでしょう。

参考:http://www.revulo.com/blog/20070628.html

DISTINCT+ORDER BY

 こういうことはできないということをようやく理解しました。DISTINCTの代わりにGROUP BYを使えば何とかなる様子。

SELECT DISTINCT c1,c2 FROM table ORDER BY c3;

 テーブルにもよりそうですが、たぶんエラー。

SELECT c1,c2 FROM table GROUP BY c1,c2 ORDER BY max(c3);

 これなら上の期待する結果が返る。max以外にも集計関数であれば問題なさそう。ここを普通にc3と書いてしまうと、「GROUP BYにc3がありません」というエラーになる。

 うーん、SQLについては分からないことが多すぎて何とも。テクニカルエンジニアのDBあたりを勉強すれば詳しくなれるだろうか。まだまだ使いこなすには時間かかりそう。

参考:http://okwave.jp/qa2828848.html