こんにちは。きんくまです。
Flashでツールアプリを作っております。最近IDEをFlash BuilderからIntelliJ IDEAに乗り換えました。1年まえにくらいにWebStormも買っちゃったので、JetBrainsさんにお布施してますね。あーいまみたらWebStromの方はライセンス切れしてました。(でも、アップグレードできないだけで、そのバージョンで使い続けること自体は大丈夫みたい)
これでjs/TypeScriptもflash/AIRもIDEA一本でできるからいいかもと思って使ってます。
ためしてないけど、Androidも作れるの??
さてさて、クライアントから「たくさんあるファイル内の、ステージ上のオブジェクトの座標を丸めたい」というご要望がありました。
で、こういうときはjsflを使って自動で作業をさせるのですが、そんなときこんな感じのjsflがあります。
var sel = fl.getDocumentDOM().selection[0];
sel.x = Math.round(sel.x);
sel.y = Math.round(sel.y);
(上のコードは適当なんで動かないかも。)
で、これはMovieClipのインスタンスだったり、シンボル化されているものをステージ上に置いたときには、きちんと機能するんですが、シンボル化されていないもの、例えばシェイプなんかについてはうまく機能しないのでした。
これは困りました。ググっていろいろと試みたのですが、うまくいきません。
で、結局作ったのがこれです。
function snapPixels( element ) {
/* 浮動小数点の丸め誤差のため数回まわす */
for(var i = 0; i < 5; i++){
var tmpX = element.left;
var tmpY = element.top;
var dx = Math.round(tmpX) - tmpX;
var dy = Math.round(tmpY) - tmpY;
if(dx == 0 && dy == 0){
break;
}
element.x += dx;
element.y += dy;
}
}
/* 使い方 */
var sel = fl.getDocumentDOM().selection[0];
snapPixels(sel);
snapPixelsのところが本体です。下の2行は使いかたで、実際には、ステージ上全体を捜査してループでエレメントを検出したりとかして使うことを想定してます。
flashの内部構造がどうなっているのか正直よくわからないんですが、調べてみると、シェイプの場合、element.x, element.y はプロパティパネル上のx, yとは値が違っていました。その代わりに、element.left, element.topがx,yの値になっていました。
なので、element.left, element.topを四捨五入の対象にして、x,yに差分を割り当てました。
ただ、これだけだと何故かうまくいかないことがあります。たぶん内部的に浮動小数点で座標をもっているのか(よくわかんなくて書いてます)1回ではなく3回ぐらい回すと、完全に小数点以下を0にすることができました。うーん、謎。