カスタムクラスのプロパティをfor..inで出力


wonderflに昔、こんな感じでforkしてみたものがあったんですが、理由が分からなかった部分を調べたまとめ。

通常、for..inをした場合、Objectとして作成したものは出力できますが、カスタムクラスのプロパティだとそれができません。

//Objectだとできる
for(var i:uint = 0; i < LOOP; i++){
    var id:String = 'id' + String(i+1);
    var name:String = 'name' + String(i+1);
    var obj:Object = new Object();
    obj.id = id;
    obj.name = name;
    _listObject.push(obj);
}
for(i = 0; i < LOOP; i++){
    var o:Object = _listObject[i];
    for(var prop:String in o){
        trace(o[prop]);//できる
    }
}

//カスタムクラスのプロパティはでない
for(var j:uint = 0; j < LOOP; j++){
    var id:String = 'id' + String(j+1);
    var name:String = 'name' + String(j+1);
    var obj:TestObject = new TestObject();
    //TestObjectはidとnameをpublic変数に持つものとする
    obj.id = id;
    obj.name = name;
    _listObject.push(obj);
}
for(j = 0; j < LOOP; j++){
    var o:Object = _listObject[j];
    for(var prop:String in o){
        trace(o[prop]);//何も出力されない
    }
}

何故できないのか、と考えてみたんですが、for..inする場合には、そのクラスでpropertyIsEnumerable(プロパティ名)というメソッドを使った時にtrueが帰ってくる必要がありそうです。

ただ、こちらのメソッド、Objectに定義されているものをoverrideすることはできないので、書く必要があるんですが、全てtrueが帰るようにしてもうまく動作しません。prototypeを拡張しても効果無しです。

しかし、たまたまいじっていたらpropertyIsEnumerableがtrueになった、というかfor..inで出力されるようになりました。そのクラスのprototypeにプロパティと同名の変数を定義した場合です。

Object型の場合は値を代入した瞬間に同様の処理をされているのか?とも思いますが、理由は良く分かりません。

サンプルはこちら。

どうせデバッグ用にしか使わないだろうので、処理速度がどう変わるのか、などは検証していません。これが自動化できれば凄く便利な気もします。ただそもそもプロパティの列挙をするためにプロパティを全て知らなければいけないという面倒さがありますし、整形して出力したければ、toStringを実装する時にそのように書いた方が楽な気がしますし。

というわけで、調べたことのメモでした。

Flashのライブラリから画像をエクスポートするJSFL


どうもお久しぶりです。

移転してから何も書いてなかったんですが、仕事に余裕がでてきたので何か書いてみようと思う次第であります。

今回のはFlash自体にはありそうでない機能、ライブラリにある画像をファイルとして書き出すJSFLです。

ソースはこんな感じに。

var _doc = fl.getDocumentDOM();
var _lib = _doc.library;
var _exportFolderURI = '';

function main(){
	var selectedItems = _lib.getSelectedItems();
	var numItem = selectedItems.length;
	if(numItem == 0){
		fl.trace("何かファイルを選択してください。");
	}
	else{
		_exportFolderURI = fl.browseForFolderURL('画像の保存先を選択してください');
		if(_exportFolderURI){
			for(var i = 0; i < numItem; i++){
				exportImage(selectedItems[i]);
			}
			fl.trace("エクスポートが完了しました。");
		}
		else{
			fl.trace('キャンセルしました');
		}
	}
}

/**
 * 画像ファイルだったらエクスポート
 * @param item:Item
 */
function exportImage(item){
	if(item.itemType != 'bitmap'){
		return;
	}
	var path = item.name;
	var pathAry = path.split('/');
	var name = pathAry.pop();
	var ext = '';
	if(name.indexOf('.') == -1){
		ext = (item.originalCompressionType == 'photo') ? '.jpg' : '.png';
	}
	
	item.exportToFile(_exportFolderURI + '/' + name + ext);
}
main();

現在選択しているライブラリの~とか余計な部分を省くと、

item.exportToFile(_exportFolderURI + '/' + name + ext);

だけですw 簡単ですね!CS4から使えるようになった機能なので、CS3以前では使えません。圧縮率を戻して画面のキャプチャを取れば大体はなんとかなるかもですが、アルファかかってるものは面倒そうですしね。こちらでさくっとエクスポートするのが良いかと思います。

上のコピペでもいけると思いますが、一応ファイルも。

imageExport.zip

使い方はこちらの公式資料を参考に。CS5でも同じような位置にあるかと思います。