LITTLE CLAP
FLASH枠外のマウスイベント 2010/11/17
 FLASHの中で何かをドラッグし、マウスが枠の外に出た状態になるとマウスイベントを受け取りづらくなります。
 特にMouseEvent.MOUSE_UPは確実に受け取らなければならないイベントで、テストのためサンプルを作成しました。
実行
ソースコード
SampleMouseDrag.as
package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    
    /**
     * マウスのドラッグにより円形をドラッグするサンプルプログラム
     * ドラッグ中にマウスがFLASH領域から外に出たときの処理を検証する
     * @author sc
     */
    public class SampleMouseDrag extends Sprite 
    {
        
        public function SampleMouseDrag():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // テストを行うスプライトを作成
            new DragCircle(this, 0, 0, stage.stageWidth, stage.stageHeight, 0xf0f0ff, 0x8080ff, 32);
        }
        
    }
    
}

SampleMouseDrag.as
package  
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.geom.Point;

    /**
     * 円形を表示し、マウスでドラッグする
     * @author sc
     */
    public class DragCircle extends Sprite
    {
        /** 指定された横幅 */
        private var w:Number;
        /** 指定された縦幅 */
        private var h:Number;
        /** 背景色 */
        private var colorBackground:int;
        /** 円の色 */
        private var colorCircle:int;
        /** 円の半径 */
        private var radiusCircle:Number;
        /** 円の位置 */
        private var posCircle:Point;
        /** 円をドラック中かどうか */
        private var bDragCircle:Boolean;
        /** マウスが円の上にあるかどうか */
        private var bOverCircle:Boolean;
        
        /** マウスの位置 */
        private var posCursor:Point;
        
        /// コンストラクタ 各種パラメータを指定して親スプライトへ追加する
        public function DragCircle(parent:Sprite, x:Number, y:Number,
            width:Number, height:Number,
            colorBackground:int, colorCircle:int, radiusCircle:Number) 
        {
            // 親スプライトへ追加
            parent.addChild(this);
            // 位置を変更
            this.x = x;
            this.y = y;
            // 指定されたサイズと色を保持
            this.w = width;
            this.h = height;
            this.colorBackground = colorBackground;
            this.colorCircle = colorCircle;
            this.radiusCircle = radiusCircle;
            // 円の初期位置(中央)
            posCircle = new Point(w / 2, h / 2);
            // イベント登録
            // ※ドラッグ中に領域外のマウスイベントを受け取るため、stageに登録する)
            posCursor = new Point(0, 0);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            // 初回描画
            update();
        }
        
        /// 表示を更新する
        public function update():void
        {
            graphics.clear();
            // 背景を塗りつぶす
            graphics.beginFill(colorBackground, 1);
            graphics.moveTo(0, 0);
            graphics.lineTo(w, 0);
            graphics.lineTo(w, h);
            graphics.lineTo(0, h);
            graphics.endFill();
            // 円を描画
            // ドラッグ中は円が領域外なこともあるが、表示上のみ領域内に収める
            graphics.beginFill(colorCircle, 1);
            graphics.drawCircle(
                getInnerX(posCircle.x), getInnerY(posCircle.y),
                radiusCircle);
            graphics.endFill();
        }
        
        // マウスが押されたとき呼ばれる
        private function onMouseDown(event:MouseEvent):void
        {
            if (bOverCircle)
            {
                // マウスが円の上にあればドラッグ開始
                bDragCircle = true;// ドラッグ中フラグ
                stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);// マウスを離すイベント
            }
        }
        
        // マウスが離されたとき呼ばれる
        private function onMouseUp(event:MouseEvent):void
        {
            bDragCircle = false;// ドラッグ中フラグ
            stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);// イベント解除
            // ドロップ決定位置を領域内に収める
            posCircle.x = getInnerX(posCircle.x);
            posCircle.y = getInnerY(posCircle.y);
        }

        private function onMouseMove(event:MouseEvent):void
        {
            // 前回のマウス座標を退避
            var mx:Number = posCursor.x;
            var my:Number = posCursor.y;
            // 現在のマウス座標を取得する
            // ※領域外でも正しく取得するため、stageのマウス座標からスプライト座標を引いて求める
            posCursor.x = event.stageX - x;
            posCursor.y = event.stageY - y;
            // マウスと円の中心の距離が半径以下か調べ、変化があればマウス形状を変更する
            if (bOverCircle != Point.distance(posCircle, posCursor) <= radiusCircle)
            {
                bOverCircle = !bOverCircle;
                this.buttonMode = bOverCircle;
            }
            // ドラッグ中なら円を移動する
            if (bDragCircle)
            {
                // 現在のマウス座標から、前回のマウス座標を引いた分だけ移動する
                posCircle.x += posCursor.x - mx;
                posCircle.y += posCursor.y - my;
                // 画面を更新する
                update();
            }
        }
        
        // 横方向を範囲内に収めた値を返す
        private function getInnerX(x:Number):Number
        {
            if (x <     radiusCircle) { return     radiusCircle; }
            if (x > w - radiusCircle) { return w - radiusCircle; }
            return x;
        }
        
        // 横方向を範囲内に収めた値を返す
        private function getInnerY(y:Number):Number
        {
            if (y <     radiusCircle) { return     radiusCircle; }
            if (y > h - radiusCircle) { return h - radiusCircle; }
            return y;
        }
    }

}
inserted by FC2 system