AS3 Windows风格拖放

时间:2015-08-14 12:04:22

标签: actionscript-3 drag

我正在制作一个包含不同元素的不同窗口的Windows风格应用。我知道如何编写拖放功能来改变舞台上窗口的位置,但是我想在不重复无限功能的情况下为所有窗口使用单个代码。我的代码是:

public function fl_WindowDrag(event: MouseEvent): void {
        instance.startDrag();
    }

    public function fl_WindowDrop(event: MouseEvent): void {
        instance.stopDrag();
    }

我希望从所选窗口自动恢复该名称,是否可能? 我希望你理解我的需要 任何帮助都被广泛接受 提前致谢

package {

import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.display.MovieClip;

public class MainTimeline extends MovieClip {

    //Variabili
    public var VFullscreen: int = 1;

    //Import var        
    public var VTerminal: Terminal = new Terminal();
    public var nTerminal:String;

    public function MainTimeline(): void {

        stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

        //Import

        //Terminal
        VTerminal.x = 288;
        VTerminal.y = 384;
        stage.addChild(VTerminal);


        //Event Listeners
        //addEventListener(MouseEvent.CLICK, fl_BringToFront);
        VTerminal.addEventListener(MouseEvent.MOUSE_DOWN, fl_WindowDrag);
        VTerminal.addEventListener(MouseEvent.MOUSE_UP, fl_WindowDrop);
    }

    //public functions

    //Gestione Fullscreen

    public function fl_Fullscreen(event: MouseEvent): void {
        switch (VFullscreen) {
            case 0:
                stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
                VFullscreen = 1;
                break;
            case 1:
                stage.displayState = StageDisplayState.NORMAL;
                VFullscreen = 0;
                break;
        }
    }

    public function fl_FSCheck(event: Event): void {
        if (stage.displayState == StageDisplayState.NORMAL) {
            VFullscreen = 0;
        }
        if (stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE) {
            VFullscreen = 1;
        }
    }

    //Primo Piano Finestre
    public function fl_BringToFront(event: MouseEvent): void {
        this.addChild(event.currentTarget as DisplayObject);
    }


    public function fl_WindowDrag(event: MouseEvent): void {
        event.currentTarget.startDrag();
        nTerminal = event.currentTarget.name.toString();
        trace(nTerminal);
    }

    public function fl_WindowDrop(event: MouseEvent): void {
        event.currentTarget.stopDrag();
    }

    //Chiusura
    public function fl_Close(event: MouseEvent): void {
        stage.nativeWindow.close();
    }

    //Apertura/Chiusura Terminal
    public function fl_Terminal(event: MouseEvent): void {
        if (contains(VTerminal)) {
            removeChild(VTerminal);
        } else {
            VTerminal.x = 288;
            VTerminal.y = 320;
            addChild(VTerminal);
        }
    }

}

}

2 个答案:

答案 0 :(得分:0)

您可以使用鼠标事件的targetcurrentTarget属性来引用触发事件的实例,如下所示(我尚未测试此代码):

public function fl_WindowDrag(event: MouseEvent): void {
    event.currentTarget.startDrag();
}

这样您就可以将事件处理程序添加到多个实例中。您可以阅读有关events properties here

的更多信息

答案 1 :(得分:0)

有很多方法可以做到这一点。 您可以为将继承此行为的所有窗口准备基类,如果您计划设计十几个窗口,这是您应该考虑的定义。另一种方法是创建sperarate类,设计为只执行此操作并注册所需的所有窗口。 但是既然你问这是否可能,我会建议你尝试一些第三方库。

GreenShock有一个很好的工具,但我没有使用他们的libralies一段时间,我不知道他们的licecing程序是什么。

如果你不喜欢它,你可以使用我前一段时间制作的代码。 它很容易使用,但它没有完全实现(不能旋转等),文档非常弱,但如果你有兴趣,我可以帮助你。 您需要做的就是传递您想要移动的物体以及一些贝司属性:

TransformTool.addClient(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Array = null, dragBounds:Array = null, grabRange:Number = 5):TransformData
  • terget - 那将是你的窗口。
  • operations - 表示转换类型(比例,拖动,旋转)的位标志
  • edgesMask - 定义哪些边应该参与缩放操作(左,右,上,下)的位标志,所有这些标志值以及操作标志都可以在TransformData类中找到。
  • sizeBounds - 对于with和height,数组contian最小和最大缩放对象大小。
  • dragBounds - 拖曳物体的位置边界。基本上这些是flash Rectangle class。
  • 的参数
  • grabRange - 从鼠标到边缘的距离,您可以抓住并抓住边缘(或角落的边缘)。您也可以使用鼠标在对象外部抓取边缘,并一次缩放两个单独的对象边缘。

因此假设ww2是您的窗口,使用情况如下:

    TransformTool.addClient(w, TransforData.SCALE|TransformData.DRAG, TransformData.BOTTOM_EDGE|TransformData.RIGHT_EDGE, null, null, 10);
    TransformTool.addClient(w2, 3, 15, [20, 10, 350, 350], [100, 100, 600, 500], 10);

这只是使用它所需的这一行。 如果要更改光标,还可以添加侦听器。

TransformTool.eventDispatcher.addEventListener(TransformToolEvent.EDGES_HIT, transformTestHit);
private function transformTestHit(e:TransformToolEvent):void 
{
    trace(TransformData(e.data).hitEdges);
}

以下是所涉及的所有代码。您可以根据需要使用它,但要注意TransformTool是静态类并且只使用一个阶段实例。 我想在Air中开发应用程序并使用您需要修改此代码的本机窗口,因为每个导航窗口实例都有自己独特的阶段。

TransformTool类:

package utils  
{
    import flash.display.DisplayObject;
    import flash.display.InteractiveObject;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    /**
     * ...
     * @author Audionysos
     */
    public class TransformTool
    {
        private static var clients:Vector.<TransformData> = new Vector.<TransformData>();
        private static var transforming:Vector.<TransformData> = new Vector.<TransformData>();
        private static var _stage:Stage;
        public static var checkEdgesOnMMove:Boolean = true;
        private static var _eventDispatcher:EventDispatcher = new EventDispatcher();

        public static function addClient(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Array = null, dragBounds:Array = null, grabRange:Number = 5):TransformData {
            var sBR:Rectangle;
            var dBR:Rectangle;
            if (sizeBounds) sBR = new Rectangle(sizeBounds[0], sizeBounds[1], sizeBounds[2], sizeBounds[3]);
            if (dragBounds) dBR = new Rectangle(dragBounds[0], dragBounds[1], dragBounds[2], dragBounds[3]);
            var td:TransformData = new TransformData(target, operations, edgesMask, sBR, dBR, grabRange);
            if (operations & TransformData.SCALE) td.allowDrag = true;
            clients.push(td);

            if (stage) return td;
            if (!target.stage) target.addEventListener(Event.ADDED_TO_STAGE, onStage);
            else { stage = target.stage; addStageListeners(); }
            return td;
        }

        /**
         * Return TransformData object associated with given target.
         * @param   target object associated with searched TransformData. 
         * @return  TransformData object associated with given target.
         */
        static public function getTransformData(target:InteractiveObject):TransformData {
            for (var i:int = 0; i < clients.length; i++){
                if (clients[i].targetObject == target) return clients[i];
            }return null;
        }

        /**
         * Mouse position relative to specifed object.
         * @param   target InteractiveObject or TransformData object.
         * @return Mouse position relative to specifed object.
         */
        static public function getTargetMouse(target:*):Point 
        {
            var t:InteractiveObject = target as InteractiveObject;
            if (!t && target as TransformData) t = TransformData(target).targetObject;
            else throw new Error ("property object must be of type InteractiveObject or TransformData");
            return new Point(t.parent.mouseX, t.parent.mouseY);
        }

        /**
         * Adds MOUSE_DOWN and MOUSE_UP listener for current stage;
         */
        static private function addStageListeners():void 
        {
            //trace("TT adding stage listeners");
            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
        }

        static private function onStage(e:Event):void 
        {
            //trace("TT client on stage");
            InteractiveObject(e.target).removeEventListener(Event.ADDED_TO_STAGE, onStage);
            stage = InteractiveObject(e.target).stage;
            addStageListeners();
        }

        static private function onMUp(e:MouseEvent):void 
        {
            for (var i:int = 0; i < transforming.length; i++){
                transforming[i].isTransforming = false;
            }
            transforming =  new Vector.<TransformData>();
        }

        static private function onMDown(e:MouseEvent):void 
        {
            //trace("TT MousDown");
            findAffectedObjects();
        }

        static private function findAffectedObjects():void 
        {
            for (var i:int = 0; i < clients.length; i++) {
                clients[i].hitEdges = findEdges(clients[i]);
                if (!clients[i].hitEdges) continue;
                //trace("TT got R", clients[i].hitEdges);
                transforming.push(clients[i]);
                clients[i].isTransforming = true;
                clients[i].updateMouseVector();
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
            }
        }

        static private function onMMove(e:MouseEvent):void 
        {
            //trace("Transforming", transforming.length);
            if (TransformTool.checkEdgesOnMMove) dispatchEdges();
            //trace("TT Moving");
            for (var i:int = 0; i < transforming.length; i++) {
                if (transforming[i].operations & TransformData.ROTATE) rotateTarget();
                //if (!checkEdgesOnMMove)
                transforming[i].updateMouseVector();
                scaleTarget(transforming[i]);
                fixSize(transforming[i]);
                fixPlacement(transforming[i]);
            }
        }

        /**
         * Performs fingEdges() operation on each client TransformData object and dispatches EDGES_HIT event if result is different form last hitEdges state;
         */
        static private function dispatchEdges():void 
        {
            for (var i:int = 0; i < clients.length; i++) {
                if (clients[i].isTransforming) continue;
                var r:uint = findEdges(clients[i]);
                if (r != clients[i].hitEdges) {
                    clients[i].hitEdges = r;
                    _eventDispatcher.dispatchEvent(new TransformToolEvent(TransformToolEvent.EDGES_HIT, clients[i]));
                }
            }
        }

        static private function rotateTarget():void 
        {

        }

        /**
         * If a part of an object is outside defined dragBounds rectangle area it will move this object to closest allowed position.
         * @param   td
         */
        static public function fixPlacement(td:TransformData):void 
        {
            if (!td.dragBounds) return;
            td.targetObject.x = Math.max(td.targetObject.x, td.dragBounds.x);
            td.targetObject.x = Math.min(td.dragBounds.right - td.targetObject.width, td.targetObject.x);
            td.targetObject.y = Math.max(td.targetObject.y, td.dragBounds.y);
            td.targetObject.y = Math.min(td.dragBounds.bottom-td.targetObject.height, td.targetObject.y);
        }

        /**
         * Changes the object to fit min/max size defined in sizeBounds object of the transformation data.
         * @param   td
         */
        static public function fixSize(td:TransformData):void 
        {
            if (!td.sizeBounds) return;
            td.targetObject.width = Math.min(td.targetObject.width, td.sizeBounds.width);
            td.targetObject.width = Math.max(td.targetObject.width, td.sizeBounds.x);
            td.targetObject.height = Math.min(td.targetObject.height, td.sizeBounds.height);
            td.targetObject.height = Math.max(td.targetObject.height, td.sizeBounds.y);
        }

        /**
         * Scales the object accordingly to grabed edges and move of the mouse.
         * @param   td
         */
        static public function scaleTarget(td:TransformData):void 
        {
            //trace("TT mouse vector", td.mouseVector);
            var rD:Point = td.mouseVector//new Point(td.mouseVector.x * td.targetObject.parent.scaleX, td.mouseVector.y * td.targetObject.parent.scaleY); //relativeDisplacement
            if (td.hitEdges & TransformData.LEFT_EDGE) { td.targetObject.width -= rD.x; td.targetObject.x += rD.x; }
            if (td.hitEdges & TransformData.RIGHT_EDGE) { td.targetObject.width += rD.x; }
            if (td.hitEdges & TransformData.TOP_EDGE) { td.targetObject.height -= rD.y; td.targetObject.y += rD.y; }
            if (td.hitEdges & TransformData.BOTTOM_EDGE) { td.targetObject.height += rD.y; }

        }

        /**
         * Check if mouse position is in grab range to any of specified object edge.
         * @param   target examined object
         * @param   grabRange minimal distance from mouse position to edge of the object. 
         * @return  resul of the inspection.
         */
        static public function findEdges(td:TransformData):uint 
        {
            if (!isMouseNearTarget(td)) return 0;
            var t:InteractiveObject = td.targetObject;
            var gR:Number = td.grabRange;
            var r:uint;
            if (Math.abs(t.x - t.parent.mouseX) < gR && t.parent.mouseX) r |= TransformData.LEFT_EDGE;
            if (Math.abs(t.x + t.width- t.parent.mouseX) < gR) r |= TransformData.RIGHT_EDGE;
            if (Math.abs(t.y - t.parent.mouseY) < gR) r |= TransformData.TOP_EDGE;
            if (Math.abs(t.y + t.height - t.parent.mouseY) < gR) r |= TransformData.BOTTOM_EDGE;
            return r;
        }

        /**
         * Check if mouse relative position is cantained within target rectangle + grabRange;
         * @param   td object to examine.
         * @return  true if mouse is near object (edges can be grabbed);
         */
        static public function isMouseNearTarget(td:TransformData):Boolean 
        {
            td.updateMouseVector();
            var exRect:Rectangle = td.targetObject.getRect(td.targetObject.parent).clone();
            exRect.inflate(td.grabRange, td.grabRange);
            return exRect.containsPoint(td.mouseStart);
        }

        /**
         * Dispatches events associated with transformed client objects.
         * TransformToolEvent contains reference to interested TransformData object.
         * @eventType TransformToolEvent.EDGE_HIT dispatched when mouse cursor is close enought client object edges to let it to be scaled.
         * You can for example use it's hitEdges property to change cursor icon accordingly.
         */
        static public function get eventDispatcher():EventDispatcher 
        {
            return _eventDispatcher;
        }

        /**
         * Stage property on which mouse events will be proceded.
         * This will be set automaticly from client object (it it was null before).
         */
        static public function get stage():Stage 
        {
            return _stage;
        }

        static public function set stage(value:Stage):void 
        {
            if (_stage) {
                _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
                _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMUp);
                _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMDown);
            }
            _stage = value;
            addStageListeners();
            if(checkEdgesOnMMove) value.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
        }
    }

}

TransformData类:

package utils  
{
    import flash.display.InteractiveObject;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    /**
     * ...
     * @author Audionysos
     */
    public class TransformData 
    {
        public static const SCALE:uint = 1;
        public static const DRAG:uint = 2;
        public static const ROTATE:uint = 4;

        public static const TOP_EDGE:uint = 1;
        public static const RIGHT_EDGE:uint = 2;
        public static const BOTTOM_EDGE:uint = 4;
        public static const LEFT_EDGE:uint = 8;

        public var targetObject:InteractiveObject;
        public var grabRange:Number;
        public var sizeBounds:Rectangle;
        public var dragBounds:Rectangle;
        public var mouseStart:Point;
        public var mouseVector:Point;
        public var hitEdges:uint;
        public var edgesMask:uint;
        public var operations:uint;
        public var isTransforming:Boolean;

        private var _allowDrag:Boolean;
        private var isDraging:Boolean;

        public function TransformData(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Rectangle = null, dragBounds:Rectangle = null, grabRange:Number = 5) 
        {
            targetObject = target;
            this.sizeBounds = sizeBounds;
            this.dragBounds = dragBounds;
            this.grabRange = grabRange;
            this.edgesMask = edgesMask;
            this.operations = operations;
        }

        public function updateMouseVector () {
            var mP:Point = new Point(targetObject.parent.mouseX, targetObject.parent.mouseY);
            if (!mouseStart) mouseStart = mP;
            mouseVector = mP.subtract(mouseStart);
            mouseStart = mP;
        }

        public function get allowDrag():Boolean 
        {
            return _allowDrag;
        }

        public function set allowDrag(value:Boolean):void 
        {
            if (_allowDrag && !value) {
                targetObject.stage.removeEventListener(MouseEvent.MOUSE_UP, onMUp);
                targetObject.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
                if (isDraging) targetObject.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
            }
            _allowDrag = value;
            if (value) targetObject.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
        }

        private function onMDown(e:MouseEvent):void 
        {
            isTransforming = true;
            mouseStart = TransformTool.getTargetMouse(this);
            targetObject.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
            targetObject.stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
        }

        private function onMUp(e:MouseEvent):void 
        {
            isTransforming = false;
            targetObject.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
        }

        private function onMMove(e:MouseEvent):void 
        {
            updateMouseVector();
            targetObject.x += mouseVector.x;
            targetObject.y += mouseVector.y;
            TransformTool.fixPlacement(this);
        }               
    }

}

TransformToolEvent:

package utils 
{
    import flash.events.Event;

    /**
     * ...
     * @author Audionysos
     */
    public class TransformToolEvent extends Event 
    {
        public static const EDGES_HIT:String = "edgesHit";
        private var _data:TransformData;

        public function TransformToolEvent(type:String, data:TransformData, bubbles:Boolean=false, cancelable:Boolean=false) { 
            super(type, bubbles, cancelable);
            _data = data;
        } 

        public override function clone():Event { 
            return new TransformToolEvent(type, _data, bubbles, cancelable);
        } 

        public override function toString():String { 
            return formatToString("TransformToolEvent", "type", "bubbles", "cancelable", "eventPhase", "data"); 
        }

        public function get data():TransformData {
            return _data;
        }

    }

}