本教程將引導你使用 ActionScript 3.0 製作一組具有 3D 立體感的互動圖標旋轉動畫:滑鼠點擊任一圖標,該圖標會平滑旋轉至最前端並放大顯示,同時根據虛擬橢圓軌道自動調整透明度與縮放,營造真實的景深效果。

整個系統包含三大核心模組:
alpha、scaleX、scaleY 以模擬 3D 景深。setChildIndex),確保「近大遠小、近遮遠」的視覺邏輯。ENTER_FRAME 事件,以緩動公式 speed += (endAngle - speed) * 0.2 平滑旋轉至目標位置,到達後自動移除事件監聽。include "Math2.as"; // 自訂三角函數庫:angleToRadian, sinD, cosD, atan2D
stage.frameRate = 30;
var disx:Number = 200; // 橢圓 X 軸半徑
var disy:Number = 10; // 橢圓 Y 軸半徑(扁平化產生 3D 感)
var speed:Number = 0; // 當前旋轉速度
var endAngle:Number = 90; // 目標角度
var tempAngle:Number = 0; // 累積角度
var isRotating:Boolean = true;
var menu:Sprite = new Sprite();
menu.x = 300; menu.y = 200;
menu.addEventListener(Event.ENTER_FRAME, moveMenu);
addChild(menu);
initMenu(5); // 建立 5 個圖標
function initMenu(n:int):void {
for (var i:int = 0; i < n; i++) {
var mc:MovieClip = new IconMenu(); // 庫中連結類別
mc.scaleX = mc.scaleY = 0.5;
mc.addEventListener(MouseEvent.MOUSE_DOWN, startRotation);
menu.addChild(mc);
}
}
function startRotation(e:MouseEvent):void {
var currentIcon:MovieClip = e.target as MovieClip;
// 根據點擊圖標當前位置計算目標角度
endAngle = atan2D(currentIcon.y, cosD(currentIcon.angle) * disy);
endAngle = (endAngle > -180 && endAngle < -90) ? -270 - endAngle : 90 - endAngle;
initAngle(true); // 重置速度、鎖定旋轉狀態
menu.addEventListener(Event.ENTER_FRAME, moveMenu);
}
function moveMenu(e:Event):void {
var iconCount:int = menu.numChildren;
var depthArray:Array = new Array();
var angle:Number = 360 / iconCount;
for (var z:int = 0; z < iconCount; z++) {
var mc:MovieClip = menu.getChildAt(z) as MovieClip;
mc.gotoAndStop(z + 1); // 切換圖標外觀
// 計算當前角度並映射到橢圓軌道
mc.angle = tempAngle + speed + angle * z;
mc.x = cosD(mc.angle) * disx;
mc.y = sinD(mc.angle) * disy;
depthArray[z] = mc;
// 根據 y 座標動態調整視覺屬性
setProp(mc, "alpha");
setProp(mc, "scaleX", 0.2, 0.7);
setProp(mc, "scaleY", 0.2, 0.7);
}
arrange(depthArray); // 重新排序顯示層級
// 緩動旋轉核心公式
speed += (endAngle - speed) * 0.2;
if (Math.abs(speed - endAngle) < 1) {
menu.removeEventListener(Event.ENTER_FRAME, moveMenu);
initAngle(false); // 解鎖旋轉狀態
}
}
function arrange(depthArray:Array):void {
depthArray.sortOn("y", Array.NUMERIC); // y 小(遠)在前,y 大(近)在後
var i:int = depthArray.length;
while (i--) {
menu.setChildIndex(depthArray[i], i); // 近的疊在遠的上面
}
}
function setProp(mc:MovieClip, prop:String, n1:Number = 0.5, n2:Number = 1):void {
// 將 y ∈ [-2*disy, 0] 映射到 [n1, n2]
mc[prop] = ((mc.y + 2 * disy) / disy - 1) / 2 * (n2 - n1) + n1;
}
function angleToRadian(angle:Number):Number { return angle * (Math.PI / 180); }
function radianToAngle(radian:Number):Number { return radian * (180 / Math.PI); }
function sinD(angle:Number):Number { return Math.sin(angleToRadian(angle)); }
function cosD(angle:Number):Number { return Math.cos(angleToRadian(angle)); }
function atan2D(y:Number, x:Number):Number { return radianToAngle(Math.atan2(y, x)); }
MouseEvent.MOUSE_WHEEL 動態調整 speed。KeyboardEvent.KEY_DOWN 監聽,左右鍵修改 endAngle。MOUSE_OVER/MOUSE_OUT 事件中臨時放大 scaleX/scaleY。Loader 類動態載入圖片替代庫中元件,實現資料驅動。| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 圖標重疊順序錯誤 | arrange() 未正確按 y 排序 | 確認 depthArray.sortOn("y", Array.NUMERIC) 且 setChildIndex 索引遞增 |
| 旋轉卡頓或停止 | ENTER_FRAME 重複註冊或未移除 | 檢查 initAngle() 中 isRotating 狀態鎖定邏輯 |
| 圖標軌道非橢圓 | disx/disy 設定不當 | 調整 disy 較小(如 10)產生扁平橢圓,增強 3D 感 |
此範例展示了 AS3 結合基礎三角幾何、顯示列表管理、緩動動畫與事件驅動編程,僅用約 100 行核心代碼即可實現極具視覺衝擊力的 3D 互動效果。掌握這套「橢圓軌道 + 深度排序 + 緩動旋轉」核心模式,即可輕鬆擴展至相册輪播、產品展示、選單導航等多種實戰場景。