回転するメニュー
最近よく見かける、3Dに回転するFlashメニュー。
オブジェクト指向で簡単に。円運動、Observerパターン、3Dなど。
がんばって、簡単に、作ってみました。製作時間は1時間半くらいです。
何回かまわすと、5つのアイテムの足並みがズレてしまうところが難点ですけど、今回は、あんまりこだわらないことにします。
(次回で解決してます)
では、円をえがく動きから、徐々に考えていきます。
円運動をするMovieClipは、次のようになります。
三角関数を使いますが、高校数学くらいの教科書をひっくり返せば、公式としてかいてあります。公式ですから、理屈なんて考えなくても・・・
class MoveOnCircle extends MovieClip{
var ANGULAR_VELOCITY = 5;//角速度
var CENTER_X = 50;//円の中心座標
var CENTER_Y = 50;
var RADIUS = 30;//円の半径
var angle = 0;
function onEnterFrame(){
_x = RADIUS * Math.cos( angle*Math.PI/180 ) + CENTER_X;
_y = RADIUS * Math.sin( angle*Math.PI/180 ) + CENTER_Y;
angle += ANGULAR_VELOCITY;
//1周したら角度をリセット
if(angle >= 360) angle -= 360;
}
}
このクラスを適当なシンボルにリンクすると、
となります。複数のインスタンスを生成してみると、
attachMovie('item','item1',0,{angle:0});
attachMovie('item','item2',1,{angle:72});
:
と、なります。
今度は、マウスクリックしたインスタンスが、一番下(90度)で止まるようにします。
この制御が、今回一番難しいところ。やりかたはいろいろあると思いますが、ここでは、Observerパターンというものを使ってみます。
下の絵のようなことをプログラムすると思ってください。
では、まず、上で作ったMoveOnCircleに、動き出す条件と止まる条件を追加していきます。
class MoveOnCircle extends MovieClip{
:
var _stopIt = true;
var _selected = false;
function stopIt(){
_stopIt = true;
_selected = false;
}
function moveIt(){
_stopIt = false;
}
function onRelease(){
_selected = true;
_root.notifySelected(this); //私が選択されました。
}
function onEnterFrame(){
if( _stopIt ) return;
if( _selected && angle > 84 && angle <= 96){
_root.nofityStopAll(); //一番下に着きました。
}
:
}
}
そして、オブザーバ(ここでは_root)に次のように、各インスタンスに指令を出すコードを書きます。
//まとめて監視、命令するために、
//インスタンスを配列などで束ねておく。
var items:Array = new Array();
items.push(item1);
items.push(item2);
:
function notifySelected( item ){
//よし、みんな回れー!
for( var i = 0 ; i < items.length; i++ ){
items[i].moveIt();
}
}
function nofityStopAll(){
//よし、みんな止まれー!
for( var i = 0 ; i < items.length; i++ ){
items[i].stopIt();
}
}
で、↓こうなります。
ここまでできれば、あとは簡単。全体を斜めにして、3D効果を出せばいい。
しかし3Dというと、ちょっと複雑な数学になってしまうので、ここでは、なんちゃって3Dで切り抜けましょう(本格的な3D計算は、こちらにエントリしました)。
まず、円運動をちょっと縦につぶして楕円運動にします。これは簡単。半径(RADIUS)を、たてよこに分けてやればOK。
RADIUS_X = 100;
RADIUS_Y = 20;
_x = RADIUS_X * Math.cos( ~
_y = RADIUS_Y * Math.sin( ~
あと、遠くのものは、小さく、表示を薄く、してやれば、それっぽくなります。MoveOnCircle._yの変化幅は
(CENTER_Y-RADIUS_Y) 以上、(CENTER_Y+RADIUS_Y) 以下
ですから、onEnterFrameで、
_xscale = _yscale = _alpha = _y / (CENTER_Y+RADIUS_Y) * 100;
としておけば、うまい具合に立体的になります。
あと、選択したインスタンスの深度を一番高くしてやる必要もありますね(ヒント:swapDepths)。

