萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 軟體知識 >  >> 影像處理 >> Flash 教學

Flash AS3 3D 選單教學:旋轉立體菜單動畫

利用 AS3 簡易 3D 透視投影(無需 Stage3D),結合三角函數計算圓周分佈、縮比與深度排序,打造滑鼠垂直位置控制旋轉速度的立體旋轉選單。

製作流程

1. 建立選單項目元件

  • 新建文件 550×400px。
  • 圓角矩形工具畫 158×35px 長方形,描邊 8px 白色,填充 #0F7E88。
  • 轉為影片剪輯 Menu Item,註冊點中心。
  • 進入編輯模式,加入動態文字欄位實例名 menuItemText,嵌入字符(基本拉丁、標點)。
  • 回主場景刪除舞台實例,改由代碼動態生成。
  • 庫中右鍵 Menu Item → 連結/屬性 → 勾選為 ActionScript 導出,類別名 MenuItem,基類 flash.display.Sprite。

2. 文件類 / 第 1 幀完整代碼

package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import caurina.transitions.Tweener; // 需外部庫,可改用原生 Tween

    public class Menu3D extends Sprite {
        private const NUM_ITEMS:uint = 20;
        private var menuItems:Array = [];
        private var focalLength:Number = 350;
        private var vanishingPointX:Number = stage.stageWidth / 2;
        private var vanishingPointY:Number = stage.stageHeight / 2;
        private var angleSpeed:Number = 0;
        private var radius:Number = 128;
        private var angleDiff:Number = Math.PI * 2 / NUM_ITEMS; // 360° 平均分佈

        public function Menu3D() {
            // 建立選單項目
            for (var i:uint = 0; i < NUM_ITEMS; i++) {
                var item:MenuItem = new MenuItem();
                item.buttonMode = true;
                item.mouseChildren = false;
                item.menuItemText.text = "Menu " + i;

                var startAngle:Number = angleDiff * i;
                item.currentAngle = startAngle;
                item.xpos3D = -radius * Math.cos(startAngle) * 0.5;
                item.ypos3D = radius * Math.sin(startAngle);
                item.zpos3D = radius * Math.cos(startAngle);

                updateItemTransform(item);
                addChild(item);
                menuItems.push(item);

                item.addEventListener(MouseEvent.MOUSE_OVER, onOver);
                item.addEventListener(MouseEvent.MOUSE_OUT, onOut);
                item.addEventListener(MouseEvent.CLICK, onClick);
            }

            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        private function updateItemTransform(item:MenuItem):void {
            var scaleRatio:Number = focalLength / (focalLength + item.zpos3D);
            item.scaleX = item.scaleY = scaleRatio;
            item.x = vanishingPointX + item.xpos3D * scaleRatio;
            item.y = vanishingPointY + item.ypos3D * scaleRatio;
            item.alpha = 0.3 + scaleRatio * 0.7; // 遠淡近實
        }

        private function onEnterFrame(e:Event):void {
            // 滑鼠 Y 控制旋轉速度
            angleSpeed = (mouseY - stage.stageHeight / 2) * 0.0002;

            for each (var item:MenuItem in menuItems) {
                item.currentAngle += angleSpeed;
                item.xpos3D = -radius * Math.cos(item.currentAngle) * 0.5;
                item.ypos3D = radius * Math.sin(item.currentAngle);
                item.zpos3D = radius * Math.cos(item.currentAngle);
                updateItemTransform(item);
            }
            sortZ();
        }

        private function sortZ():void {
            // 依 zpos3D 降序排列(遠在前、近在後),確保遮擋正確
            menuItems.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING);
            for (var i:int = 0; i < menuItems.length; i++) {
                setChildIndex(menuItems[i], i);
            }
        }

        private function onOver(e:MouseEvent):void {
            Tweener.addTween(e.currentTarget, {scaleX:1.2, scaleY:1.2, time:0.3, transition:"easeOutQuad"});
        }
        private function onOut(e:MouseEvent):void {
            Tweener.addTween(e.currentTarget, {scaleX:1, scaleY:1, time:0.3, transition:"easeOutQuad"});
        }
        private function onClick(e:MouseEvent):void {
            trace("Clicked: " + e.currentTarget.menuItemText.text);
        }
    }
}

3. 關鍵技術解析

  • 簡易 3D 投影:scaleRatio = focalLength / (focalLength + z) 模擬透視縮放,x = vpX + x3D * scaleRatio、y = vpY + y3D * scaleRatio 投影至 2D 舞台。
  • 橢圓軌道:xpos3D = -radius * cos(a) * 0.5、zpos3D = radius * cos(a) 形成 XZ 平面橢圓,Y 軸用 sin(a) 產生上下起伏。
  • 深度排序:每幀 sortOn("zpos3D", DESCENDING) 並重設 setChildIndex,確保遠處項目被近處遮蓋。
  • 滑鼠控速:angleSpeed = (mouseY - centerY) * 0.0002,滑鼠越偏離中心旋轉越快。

4. 依賴與替代

代碼使用 caurina.transitions.Tweener(舊版 GreenSock 前身),現代專案建議改用 GSAP 3(gsap.to())或原生 fl.transitions.Tween 移除外部依賴。

此範例展示了純 AS3 實現偽 3D 旋轉選單的核心數學與渲染邏輯,是理解 3D 投影、深度排序、互動控制的優秀練習專案。

copyright © 萬盛學電腦網 all rights reserved