需求:同一滑鼠左鍵同時實現**拖拽移動**與**點擊旋轉** MC。
常見方案:拖拽用 `MOUSE_DOWN/MOUSE_UP`,旋轉需 `SHIFT+CLICK`,體驗割裂。
嘗試合併:`MOUSE_DOWN+MOUSE_UP` 相當於 `CLICK`,導致每次釋放即旋轉,非預期。
**區分「點擊」與「拖拽」的本質差異:滑鼠位置是否發生位移。**
- 點擊:按下 → 釋放,`stageX/stageY` **無變化**。
- 拖拽:按下 → 移動 → 釋放,`stageX/stageY` **有變化**。
package {
import flash.display.*;
import flash.geom.Point;
import flash.events.*;
public class Main extends Sprite {
private var mc:MC; // 庫中連結類為 MC 的影片剪輯
private var clickOffset:Point; // 按下時滑鼠與 MC 相對偏移
private var mouseLoc:Point; // 按下時滑鼠舞台座標
public function Main() {
mc = new MC();
addChild(mc);
mc.x = 200;
mc.y = 200;
mc.addEventListener(MouseEvent.CLICK, rot); // 點擊旋轉
mc.addEventListener(MouseEvent.MOUSE_DOWN, startDrag); // 按下準備拖拽
addEventListener(Event.ENTER_FRAME, doDrag); // 幀循環拖拽
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrag); // 階段釋放
}
private function startDrag(e:MouseEvent):void {
mouseLoc = new Point(e.stageX, e.stageY); // 記錄按下位置
clickOffset = new Point(e.stageX - mc.x, e.stageY - mc.y); // 計算偏移
}
private function doDrag(e:Event):void {
if (clickOffset == null) return; // 未按下
mc.x = mouseX - clickOffset.x;
mc.y = mouseY - clickOffset.y;
}
private function stopDrag(e:MouseEvent):void {
clickOffset = null; // 釋放標記
}
private function rot(e:MouseEvent):void {
// 關鍵判斷:釋放位置 == 按下位置 才視為純點擊
if (!mouseLoc.equals(new Point(e.stageX, e.stageY))) return;
mc.rotation += 30; // 每次點擊旋轉 30°
}
}
}
此模式已成為 Flash/AS3 交互基礎組件庫的標準實現,推薦收藏作為 UI 組件開發範本。