BitmapのsmoothingとPixelSnappingの謎

今日FlashでBitmapをいじっているときに、Flashってこういう仕様だったっけ?という現象に出会ったのでメモ。

『ActionScript用に書き出し』するとスムージングされなくなる

『ActionScript用に書き出し』されている画像をFlashIDE上で配置すると、スムージングにチェックを入れていてもスムージングされなくなる。
ActionScript用に書き出しのチェックを外すと右の画像も左の画像と同じようにスムージングがかかる。
 

flaファイルはこちら(CS4)
 

PixelSnappingのNEVERが効かない?

上のFlashはActionScriptで配置したビットマップと、IDE上に配置してあるSpriteを毎フレーム0.1ピクセルずつ移動させたもの。ASで配置した画像は以下のようにPixelSnappingをNEVERにしているが、実際はピクセル吸着されていてスムーズに横移動していない。

ACTIONSCRIPT:
  1. var sky1:Bitmap=new Bitmap(new Sky(0,0),PixelSnapping.NEVER,true);
  2. addChild(sky1);

 
ActionScript 3.0 コンポーネントリファレンスガイドによると、PixelSnappingがAUTOのときは以下の条件でピクセルに吸着される。
 
AUTO : String = "auto"
[static]Bitmap オブジェクトの pixelSnapping プロパティで使用される定数値です。ビットマップイメージが回転または傾斜なしで、99.9% ~ 100.1% の縮尺率で描画される場合に、ビットマップイメージが最も近いピクセルに吸着することを指定します。

 
上のFlashもsky1.rotation = 0.5としたり、sky1.scaleX = 1.01とすると、ピクセル吸着しなくなるのだけど、それだとpixelSnappingのAUTOとNEVERには違いがないということになってしまう。

flaファイルはこちら(CS4)

progressionでindex.html#に飛んだときのブラウザの挙動の回避法

progression(というかswfAddress?)でトップページを/indexにしてしまうと、他ページからトップへ戻るときにURLが「index.html#」となってしまうため、ブラウザウィンドウがトップまでスクロールしてしまいます。
 
以下がその例。(一番下にメニューボタンがあるのでHOMEを押してみてください)

・Sample01
 
PAGE1やPAGE2など、他のページへの遷移時にはブラウザがスクロールしないのに、HOMEへ飛んだときだけブラウザがスクロールします。
 
Flashやjavascriptでなく、htmlを変更することでこの挙動を回避できる方法を偶然見つけました。
条件は限られますが、方法はめちゃくちゃ簡単。swfObjectで代替されるスタイルシートのdivのidをbody直下のものにするだけです。progressionで言うと、body直下のidは"content"ですが、これを"flashcontent"に変更します。
 
・Sample02(swfファイルはSample01と同じものです)
 
中身良くわかってない上での回避法なので、一応変更時には他に不具合が発生しないか良くチェックしてみてください。htmlを変更するので当然noflaの表示などはCSSの調整が必要です。

useOwnContainer=trueにaddChildしたらuseOwnContainer=trueできない

Papervision3Dのオブジェクトに透明度つけたりフィルターかけたりしたいときはuseOwnContainerというプロパティをtrueにしなければならないのですが、useOwnContainer=trueにしたオブジェクトにaddChildしたら、そのオブジェクトはuseOwnContainer=trueにできないという話。
どちらかには効くのでやりたいことができない!ということはないと思うけど、知らなかったらはまるかもしれないのでメモ。
 
以下がwonderflで検証したもの。
左が普通のPlane。右はuseOwnContainer=trueにしたDisplayObject3DにaddChildしたPlane。

 
・_containerのalphaは変えることができる
・_container.useOwnContainer = true;をコメントアウトすれば_plane2のalphaを変えれるようになる。
・ちなみにalphaとかを有効にするのはuseOwnContainer以外に、ViewportLayerを使う方法もある。そっちのほうが軽いらしい。

FLVPlaybackのSeekBarHandleにハマりまくりました


 
何回使っても良くわからないFLVPlaybackに今回もどっぷりハマりました。

FLVPlaybackのSeekBarHandleはムービーの再生位置を示してくれるもの。ドラッグして左右に動かすとビデオの巻き戻しや早送りができます。自分でこの機能を実装しようと思ったら少々面倒くさい(というかできるかあんまり自信ない)ので、FLVPlayback備え付けのSeekBarHandleがちゃんと使えれば便利なのですが、このSeekBarHandle、ちゃんと指定しているのに出てこないことが度々あったのです。

その原因が今まで解明できていなかったので、SeekBarHandleを仕事で使うのは極力避けていたのですが、つい最近原因を解明せざるを得ない場面に遭遇したので、この機会にきちんとSeekBarHandleと向かい合ってみました。
 
まず以下のような、FLVPlaybackを使用してムービーを再生させるFlvPlayerクラスを作成しました。FLVPlaybackおよびPlayPauseButtonなど各FLVPlaybackカスタムUI コンポーネントをnewして、割り当てているだけのシンプルなものです。

[以下のページなどを参考に]
FLV Playback カスタム UI コンポーネントの使用
http://www.gcommerce.com/jp/devnet/flash/articles/custom_flvcomp_03.html

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.Sprite;
  3.     import flash.events.Event;
  4.     import flash.events.MouseEvent;
  5.     import fl.video.MetadataEvent;
  6.     import fl.video.FLVPlayback;
  7.     import fl.video.VideoEvent;
  8.    
  9.     public class FlvPlayer extends Sprite {
  10.         private var _path:String;
  11.         private var flvplayback:FLVPlayback;
  12.         private var playpauseBtn:PlayPauseButton;
  13.         private var mutebtn:MuteButton;
  14.         private var seekbar:SeekBar;
  15.        
  16.         public function FlvPlayer(path:String) {
  17.             _path = path;
  18.             addEventListener(Event.ADDED_TO_STAGE, _onAdded);
  19.         }
  20.        
  21.         private function _onAdded(e:Event):void {
  22.             removeEventListener(Event.ADDED_TO_STAGE, _onAdded);
  23.            
  24.             flvplayback = new FLVPlayback();
  25.             flvplayback.width = 400;
  26.             flvplayback.height = 300;
  27.             flvplayback.x = 50;
  28.             flvplayback.source = _path;
  29.             //自動再生
  30.             //flvplayback.autoPlay = false;
  31.            
  32.             // playpauseBtn
  33.             playpauseBtn = new PlayPauseButton();
  34.             playpauseBtn.buttonMode = true;
  35.             playpauseBtn.x = 50;
  36.             playpauseBtn.y = 310;
  37.             //seekbar
  38.             seekbar = new SeekBar();
  39.             seekbar.x = 89;
  40.             seekbar.y = 317;
  41.             //mutebtn
  42.             mutebtn = new MuteButton();
  43.             mutebtn.buttonMode = true;
  44.             mutebtn.x = 427;
  45.             mutebtn.y = 310;
  46.            
  47.             flvplayback.playPauseButton = playpauseBtn;
  48.             flvplayback.muteButton = mutebtn;
  49.             flvplayback.seekBar = seekbar;
  50.            
  51.             addChild(playpauseBtn);
  52.             addChild(mutebtn);
  53.             addChild(seekbar);
  54.             addChild(flvplayback);
  55.            
  56.             addEventListener(Event.REMOVED_FROM_STAGE, _onRemoved);
  57.         }
  58.        
  59.         private function _onRemoved(e:Event):void {
  60.             removeEventListener(Event.REMOVED_FROM_STAGE, _onRemoved);
  61.             flvplayback.stop();
  62.             removeChild(seekbar);
  63.             removeChild(playpauseBtn);
  64.             removeChild(mutebtn);
  65.             removeChild(flvplayback);
  66.             seekbar = null;
  67.             playpauseBtn = null;
  68.             mutebtn = null;
  69.             flvplayback = null;
  70.         }
  71.        
  72.     }
  73. }

 
各コンポーネントはFlashデフォルトのものです。それぞれ1フレーム目に書き出す、にチェックをつけるのを忘れずに。
これでFlashの1フレーム目に以下を書いて書き出したものが

ACTIONSCRIPT:
  1. var flvplayer:FlvPlayer = new FlvPlayer("mov01.flv");
  2. addChild(flvplayer);

 
Read more »

Papervision3Dで画像がゆがむの回避する方法、どっちがいい?

Papervision3Dでオブジェクトにビットマップ画像を貼り付けたとき、画像がゆがんでしまうのを回避するにはオブジェクトのセグメント数を上げるしかないと思っていたのですが、先日会社で隣の席に座っている@morikenさんにbitmapMaterialなどの引数“precise”をtrueにすることでもゆがみを解消できることを教わったので、せっかくだしちょっと比較検証してみることにしました。
 
まずは画像のゆがみの比較です。
一番左は、普通に貼り付けただけのもの。
真ん中はnew Plane(_material, _w, _h, 4, 4)のような感じでセグメントを4つずつ分割したもの、
一番右はnew BitmapMaterial(bitmap, true)のような感じで、2つ目の引数preciseをtrueにしたものです。
何もしてないのは論外として、真ん中と右を比べると、precise=trueの方が角度によって若干ガタつきが起こっていることが分かります。


 

スピード比較

大量にオブジェクトを作ってスピード比較してみました。上がPlaneのセグメント数を4,4にしたもの、下がmaterialのpreciseをtrueにしたものです。
あからさまにpreciseをtrueにしたものの方が速いことが分かります。
 

 

 
segmentの数を2,2まで減らせばprecise=trueにしたものより速くすることができますが、その場合はprecise=trueの方がゆがみが少なく、表示がきれいになります。
 

 

結論

ほとんどの場合、セグメント数を増やすよりprecise=trueを使う方が良さそうです。セグメント数を増やすのはprecise=trueにしたものよりさらにゆがみを少なくしたい場合でしょうか。スピードは犠牲にすることになりますが、4,4以上のセグメント数にすればprecise=trueより見た目を良くできます。
 
[追記 10/03/17]
soundkitchenさんが検証ソースをwonderflでも動くようにしてくれたので、実際に試してみたい方は以下からFork

 
ソースは以下。
 
Read more »