超お手軽Dock
あちこちで公開されているMacOSXのDock風のコンポーネントですが、Boxレイアウトを応用すると結構簡単にできます。
というのも、Flex2ではコンポーネントのScaleを考慮してリアルタイムにレイアウトしてくれるため、個々のScaleを変えるだけでほかのコンポーネントが勝手によけてくれます。こういうのって、他のプラットフォームではなかなか思いつかないですよね。
ソース上の工夫としては、マウスオーバーしたときに徐々に大きくなるよう、個々のアイテムに対してエフェクトをかけています。
使い方ですが、PanelやApplicationでlayout='vertical',horizontalAlign='center'に指定し、
ZoomBoxにdirection='horizontal',verticalAlign='bottom'を指定して張り込んでやると、画面下部に表示されます。
(もとはBoxですから、アイテムは各自張り込んでください。Listではありません)
もっとかっこよくするには、鏡面加工を施したまな板(?)を張り込んでやるべきですが、それはまた今度。
import flash.display.DisplayObject; import flash.events.MouseEvent; import flash.geom.Rectangle; import flash.utils.Dictionary; import mx.containers.Box; import mx.effects.Zoom; public class ZoomBox extends Box { public static const MAX_ZOOM:Number = 2; public static const MAX_DISTANCE:Number = 200; public function ZoomBox() { super(); } protected override function childrenCreated():void { super.childrenCreated(); addEventListener(MouseEvent.MOUSE_MOVE, mouseOverHandler); addEventListener(MouseEvent.MOUSE_OUT, mouseOverHandler); } protected function mouseOverHandler(e:MouseEvent):void { e.stopImmediatePropagation(); var insideMouse:Boolean = getRect(this).contains(mouseX,mouseY); for (var i:Number = 0; i < numChildren; i++){ var child:DisplayObject = getChildAt(i); var z:Number = 1.0; if(insideMouse){ var d:Number = getDistance(i,mouseX,mouseY); if(d <MAX_DISTANCE *2){ z = Math.max(Math.cos(d/MAX_DISTANCE)*MAX_ZOOM+ 1, 1); } } applyEffect(child,z); } invalidateDisplayList(); } private function getDistance(index:int, x:Number, y:Number):Number { var child:DisplayObject = getChildAt(index); var rect:Rectangle = child.getRect(this); if(child){ var cx:Number = rect.x + child.width / 2; var cy:Number = rect.y + child.height /2; if(direction == "horizontal"){ return Math.abs(x - cx); }else{ return Math.abs(y - cy); } } return MAX_DISTANCE + 1; } private function applyEffect(child:DisplayObject, zoom:Number):void { var ef:Zoom = efDic[child] as Zoom; if(!ef){ ef = new Zoom(child); ef.duration = 100; efDic[child] = ef; } if(ef.isPlaying){ ef.stop(); } ef.zoomWidthTo = ef.zoomHeightTo = zoom; ef.play(); } private function isPlayingEffect(child:DisplayObject):Boolean { var ef:Zoom = efDic[child] as Zoom; return ef ? ef.isPlaying : false; } private var efDic:Dictionary = new Dictionary(true); }