Positionerクラスのメモ

ステージサイズの変更時に各エレメントが希望の位置に配置されるようにしたいと常々思っていて(例えば、右下にナビゲーション配置>>ブラウザウィンドウが全画面になっても右下に配置、みたいに)、そのためのクラスを少しずつ作っている。その途中経過としてのメモ。

手順としては、

  1. 以下のPositionerクラスをimport
    • var po = new Positioner("index", stage); //引数:識別子, 関連付けたいstage
  2. 追加したいMCインスタンスをAddChild
    • po.AddChild(mc, "LEFT", "BOTTOM"); //MovieClip"mc"を左下に配置

ちなみにところどころProgressionフレームワークの書き方を参考にしてみた。

/*****************************************************************
Positioner0.5 alpha2
2008.7.9
クラスベースの制作を想定。大元のPositionerインスタンスを作成し、それをContainerとしてDisplayObjectをAddchildしていく。

<今後の実装予定>
・アニメーションして移動>おそらくEnterFrame
・最小範囲設定(I.e:600より小さくなったらそれ以上中に動かさないとか)>Constructerで設定?
・alignが初期値で%配置
・AddChildのパラメータをObjectにまとめるべき?
・AddObjectAtが必要か
・ChangeAttribute?>>属性を変える関数
*****************************************************************/
package {
	import flash.display.*;
	import flash.events.Event;
	import flash.display.Stage;

	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;

	public class Positioner extends Sprite {
		/*-------------------------------------------------------------------
		インスタンス作成時のステージサイズを取得(読み取り専用)
		*/
		public function get initialStageWidth():int { return _initialStageWidth; }
		private var _initialStageWidth:int;
		
		public function get initialStageHeight():int { return _initialStageHeight; }
		private var _initialStageHeight:int;
		/*-------------------------------------------------------------------
		処理する対象を保持
		*/
		private var targetsData:Array=new Array();
		/*===================================================================
		コンストラクタ
		@id = Identifier(今のところ未使用)
		@stage = 基準になるStageインスタンス
		*/
		public function Positioner(id:String, _stage:Stage):void {
			//ContainerとしてStageに追加
			_stage.addChild(this);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			//初期ステージサイズを保持
			_initialStageWidth = stage.stageWidth;
			_initialStageHeight = stage.stageHeight;
		}
		/*===================================================================
		エレメントをPositionerコンテナの中に追加
		@target = TargetChild
		@alignV =  縦位置> TOP, BOTTOM, CENTER, null=%
		@alignH = 横位置> LEFT, RIGHT, CENTER, null=%
		@scale = スケーリングの有無
		@smooth = アニメーションしながら移動 (現在未使用)
		@offsetV = alignVからのオフセット
		@offsetH = alignHからのオフセット
		*/
		public function AddChild(target:DisplayObject, alignV:String=null, alignH:String=null, scale:Boolean=false, smooth:Boolean=false, offsetV:int=0, offsetH:int=0):void {
			addChild(target);
			var obj:Object={target:target, alignV:alignV, alignH:alignH, scale:scale, smooth:smooth, offsetV:offsetV, offsetH:offsetH};
			setPositions(obj);
			targetsData.push(obj);
			stage.addEventListener(Event.RESIZE, onResizeHandler);
		}
		/*===================================================================
		ハンドラ
		*/
		private function onResizeHandler(e:Event):void {
			for (var i=0; i<targetsData.length; i++) {
				var obj:Object=targetsData[i];
				setPositions(obj);
			}
		}
		/*===================================================================
		MCを任意の位置に移動
		*/
		private function setPositions(obj:Object):void {
			var mc=obj.target;
			var sw:int = stage.stageWidth;
			var sh:int = stage.stageHeight;
			var tmpY:Number;
			var tmpX:Number;
			//Scaling
			if (obj.scale) {
				var xScale:Number = sw / initialStageWidth;
				var yScale:Number = sh / initialStageHeight;
				var fixScale:Number = Math.max(xScale, yScale);
				mc.scaleX = mc.scaleY = fixScale;
			}
			switch (obj.alignV) {
				case "TOP" :
					tmpY = 0+obj.offsetV;
					break;
				case "BOTTOM" :
					tmpY = sh-mc.height-obj.offsetV;
					break;
				case "CENTER" :
					tmpY = sh/2-mc.height/2+obj.offsetV;
					break;
			}
			switch (obj.alignH) {
				case "LEFT" :
					tmpX = 0+obj.offsetH;
					break;
				case "RIGHT" :
					tmpX = sw-mc.width-obj.offsetH;
					break;
				case "CENTER" :
					tmpX = sw/2-mc.width/2+obj.offsetH;
					break;
			}
			mc.x = tmpX;
			mc.y = tmpY;
		}
	}
}