left,top より setPos の方が高速
レイヤーの縦横位置を変更するには
layer.left = 100;
layer.top = 100;
とする方法と
layer.setPos(100, 100);
とする方法があるが
setPos の方がはるかに高速である!
2つの方法の違い
この2つの方法はまったく同じ意味に見えるが…
実は2つの方法には大きな違いがある。
left, top の方が関数を呼び出していない分、より高速なのではないかと思うかもしれないが、
left, top はプロパティなので、実質的には関数を2回呼び出していることと同じだ。
よってむしろ setPos の方が関数呼び出し1回で済む点において高速である。
しかしそんなことは些細な違いでしかない。
それよりもずっと大きな、決定的な違いがある。
それは
無効領域の発生タイミング
にまつわる動作の違いである。
ちなみに無効領域とは、画面上において再描画が行われる領域のことである。
動作の確認
動作の違いを確認してみよう。
class TestWindow extends Window
{
function TestWindow()
{
super.Window();
// プライマリレイヤー作成
var w = 200;
var h = 200;
add(new Layer(this, null));
primaryLayer.setImageSize(w, h);
primaryLayer.setSizeToImageSize();
setInnerSize(w, h);
primaryLayer.fillRect(0, 0, w, h, 0); // 黒
}
function onKeyDown(key, shift)
{
// Enterキーが押されたらレイヤーを作成する
if(key == VK_RETURN)
{
// レイヤーを作成
var w = 100;
var h = 100;
var layer = new Layer(this, primaryLayer);
add(layer);
layer.setImageSize(w, h);
layer.setSizeToImageSize();
layer.fillRect(0, 0, w, h, 0xFFAAAAAA); // 灰
// レイヤーを移動
layer.visible = true;
layer.left = 100;
layer.top = 100;
}
}
}
var win = new TestWindow();
win.visible = true;
これを実行したらまずウィンドウを選択して Shift+F11キー を押し
更新矩形を表示するモードにする。
そして Enterキー を押すと次のようになる。
黄色い枠で示されているのが無効領域となり、再描画が行われた領域である。
細かく区切られているように見えるのは、キャッシュ効率を上げるための描画分割による作用だ。
レイヤーが移動する時、無効領域は2つ発生する。
『レイヤーが移動する前の領域』 と
『レイヤーが移動した後の領域』 だ。
画面の左上の領域が 『レイヤーが移動する前の領域』
画面の右下の領域が 『レイヤーが移動した後の領域』 である。
注目して欲しいのは、なんの関係もない右上の領域が再描画されている点だ。
では、これを setPos に置き換えて実行してみよう。
// レイヤーを移動
layer.visible = true;
layer.setPos(100, 100);
右上の領域が無駄に再描画されなくなった!
何が起きているのか
この動作の違いは、先に述べたように 『無効領域の発生タイミング』 に起因している。
無効領域は、レイヤーに対して
操作を行った直後に発生する。
left, top プロパティで位置を変更する方法の場合
left = 100; とした時点で無効領域が発生し
top = 100; とした時点で無効領域が再度発生するという動作になる。
そう、これによって右上に無駄な無効領域が発生し、無駄な再描画が行われてしまったのだ。
setPos の場合、leftとtopを両方変更してから無効領域が発生する。
よって、無駄な無効領域が発生せず、無駄な再描画も行われない。
最初に「setPos の方がはるかに高速」と言ったのはこのことである。
まとめ
このようなことからレイヤーの縦横位置を同時に変更する時は
left, top プロパティよりも setPos 関数を使うべきだと言えるだろう。