缩放盒子 ScaleBox 同时兼容Flex

发表评论 阅读评论
这是一个缩放盒子scaleBox的演示demo,如果你看不到这个flash,请到文章页面查看!

更新说明:
0.9.1 修复 缩放后托选右下角是缩放点,整个盒子一起移动的bug.
看着是不是跟QQ截屏里的缩放盒子很像啊,哈哈,就是仿照它的做的。
这个缩放盒子是为了提供给图片剪切工具用的,不是容器,不能把图片放到缩放盒子里(当然添加一个内容层也很简单) 。
但是我感觉没必要那么多功能在里面.

属性和方法:

  • dragEnable: 是否可拖动
  • scaleEnable: 是否可缩放
  • is8dot: 是否8个缩放控制点, 否则为4个缩放控制点
  • boxWidth: 缩放盒子的宽度, 仅包含黑线边框的宽度
  • boxHeight:缩放盒子的高度, 仅包含黑线边框的高度
  • resize(boxWidth:Number, boxHeight:Number):void 同时设置宽高,相比一个一个设置效率高点

事件:

  • resize: 当boxWidth,boxHeight修改后触发, 可用Event.RESIZE 常量
  • box_move:当位置改变后触发,这个没有现成的常量,请直接用 "box_move"

适用环境:

  • Flash 及 AS工程: 可以直接拿来用,无需修改
  • Flex 工程: 仅需修改基类为 UIComponent即可,其他无需修改

注意事项:

  • 缩放盒子不是容器,请不用调用向ScaleBox里添加显示对象.
  • 用AS改变宽高时,请用boxWidth,boxHeight 属性, 或,resize(boxWidth,boxHeight)方法 请不要直接设置 width,height属性
  • 由于用了fp10的鼠标样式,请设置fp版本为10, 若用fp9请删除鼠标样式相关代码

ScaleBox:

package com.litefeel.tools 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.Mouse;
    import flash.ui.MouseCursor;

    /**
     * 当修改了boxWidth,boxHeight时触发
     */
    [Event(name = "resize", type = "flash.events.Event")]

    /**
     * 当位置改变后触发,这个没有现成的常量,请直接用 "box_move"
     * @example addEventListener("box_move", moveHandler);
     */
    [Event(name = "box_move", type = "flash.events.Event")]

    /**
     * 这是一个有4个或8个缩放点的缩放盒子, 类似变形工具一样的效果<br />
     * 这个可以拖动<br />
     * 当拖动缩放点改变,或用resize方法更改尺寸后,触发resize事件<br />
     * 当改变位置后,触发move事件<br />
     * 由于用到flashplayer10的鼠标样式,请用用fp10测试<br />
     * 
     * 在Flex里使用<br />
     * 如果想在flex里应用,请将基类修改为 UIComponent <br />
     * 注意这里宽高使用的boxWidth,boxHeight, 请不要是用width,height<br/>
     * 
     * www.litefeel.com {@link http://www.litefeel.com}
     * lite3@qq.com
     * 欢迎交流学习
     * @author lite3
     * @version 0.9
     */
    public class ScaleBox extends Sprite
    {
        private var _dragEnable:Boolean = true;// 是否可拖动
        private var _scaleEnable:Boolean = true;//是否可缩放
        private var _is8dot:Boolean = true; // 是否8个控制点, false为4个, 默认8个
        private var _boxWidth:Number;
        private var _boxHeight:Number;

        private var changeW:int;            // 当前控制点 -1:左 , 0:中间  1:右边
        private var changeH:int;            // 当前控制点 -1:上 , 0:中间  1:下边

        private var isMove:Boolean = false; // 是否拖动
        private var lockX:Number;
        private var lockY:Number;

        private var bottomRightX:Number;    // 右下角x坐标(父级坐标空间)
        private var bottomRightY:Number;    // 右下角y坐标(父级坐标空间)

        private var dotList:Array = [];     // 控制点数组

        // 作为scaleBox的内容用的, 测试发现 用graphics 填充,不能很好的触发 over out事件
        private var hitSprite:Sprite;   
        private var txt:TextField;

        public function ScaleBox(boxWidth:Number = 100, boxHeight:Number = 100, is8dot:Boolean = true) 
        {
            super();
            initUI();
            // 用graphics画线,不能很好的响应 over out 事件, 则 设置本身不接受鼠标事件
            mouseEnabled = false; 
            addMouseCursorHandler();
            addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            this.is8dot = is8dot;
            resize(boxWidth, boxHeight);
        }

        /**
         * 重置 box 尺寸 
         * @param   boxWidth    <b> Number  </b> 宽度 >= 1
         * @param   boxHeight   <b> Number  </b> 高度 >= 1
         * @eventType   flash.events.Event
         */
        public function resize(boxWidth:Number, boxHeight:Number):void
        {
            if (isNaN(boxWidth) || isNaN(boxHeight)) return;
            if (boxWidth < 1 || boxHeight < 1) return;

            _boxWidth  = boxWidth;
            _boxHeight = boxHeight;
            bottomRightX = x + boxWidth;
            bottomRightY = y + boxHeight;

            txt.text = boxWidth + " * " + boxHeight;
            var halfW:Number = boxWidth  * .5;
            var halfH:Number = boxHeight * .5;

            for (var i:int = 0; i < 8; i++)
            {
                var dot:Dot = dotList[i];
                dot.x = halfW * dot.lx
                dot.y = halfH * dot.ly
            }

            this.graphics.clear();
            this.graphics.lineStyle(1);
            this.graphics.drawRect(0, 0, boxWidth, boxHeight);
            this.graphics.endFill();
            hitSprite.width = boxWidth;
            hitSprite.height = boxHeight;
            dispatchEvent(new Event(Event.RESIZE));
        }

        /**
         * 缩放盒子的宽度
         * @default 100
         */
        public function get boxWidth():Number { return _boxWidth; }
        /**
         * 缩放盒子的宽度
         * @default 100
         */
        public function set boxWidth(value:Number):void 
        {
            resize(value, _boxHeight);
        }

        /**
         * 缩放盒子的高度
         * @default 100
         */
        public function get boxHeight():Number { return _boxHeight; }
        /**
         * 缩放盒子的高度
         * @default 100
         */
        public function set boxHeight(value:Number):void 
        {
            resize(_boxWidth, value)
        }

        override public function set x(value:Number):void
        {
            if (isNaN(value)) return;

            super.x = value;
            bottomRightX = value + _boxWidth;
            dispatchEvent(new Event("box_move"));
        }

        override public function set y(value:Number):void
        {
            if (isNaN(value)) return;

            super.y = value;
            bottomRightY = value + _boxHeight;
            dispatchEvent(new Event("box_move"));
        }

        /**
         * 是否8个缩放点, 4个或8个,
         * @default true  
         */
        public function get is8dot():Boolean { return _is8dot; }
        /**
         * 是否8个缩放点, 4个或8个,
         * @default true  
         */
        public function set is8dot(value:Boolean):void 
        {
            if (_scaleEnable && _is8dot != value)
            {
                _is8dot = value;
                dotList[1].visible = value;
                dotList[3].visible = value;
                dotList[5].visible = value;
                dotList[7].visible = value;
            }
        }

        /**
         * 是否可用鼠标缩放大小
         * @default true
         */
        public function get scaleEnable():Boolean { return _scaleEnable; }
        /**
         * 是否可用鼠标缩放大小
         * @default true
         */
        public function set scaleEnable(value:Boolean):void 
        {
            if (_scaleEnable != value)
            {
                _scaleEnable = value;
                for each(var dot:Object in dotList)
                {
                    dot.visible = value;
                }
                if (value && !is8dot)
                {
                    _is8dot = !value;
                    is8dot = value;
                }
            }
        }

        /**
         * 是否可拖动
         * @default true
         */
        public function get dragEnable():Boolean { return _dragEnable; }
        /**
         * 是否可拖动
         * @default true
         */
        public function set dragEnable(value:Boolean):void 
        {
            if (_dragEnable != value)
            {
                _dragEnable = value;

                if (value) addChildAt(hitSprite, 0);
                else removeChild(hitSprite);
            }
        }

        private function mouseOverHandler(e:MouseEvent):void 
        {
            if (e.target is Dot)
            {
                Mouse.cursor = MouseCursor.BUTTON;
            }else
            {
                Mouse.cursor = MouseCursor.HAND;
            }
        }

        private function rollOutHandler(e:MouseEvent):void 
        {
            Mouse.cursor = MouseCursor.AUTO;
        }

        private function mouseDownHandler(e:MouseEvent):void 
        {
            if (e.target is Dot)
            {
                isMove = false;
                var dot:Dot = e.target as Dot;
                changeW = dot.lx -1;
                changeH = dot.ly -1;
            }else
            {
                isMove = true;
                lockX = mouseX;
                lockY = mouseY;
            }

            removeMouseCursorHandler();
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        }

        private function mouseUpHandler(e:MouseEvent):void 
        {
            stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            addMouseCursorHandler();
        }

        private function mouseMoveHandler(e:MouseEvent):void 
        {
            // 拖动
            if (isMove)
            {
                x = parent.mouseX - lockX;
                y = parent.mouseY - lockY;
            }
            // 缩放
            else
            {
                var w:Number, h:Number;
                var tx:Number = x;
                var ty:Number = y;

                if (changeW < 0) tx = mouseX + tx;
                else if (changeW > 0) bottomRightX = mouseX + tx;

                if (changeH < 0) ty = mouseY + ty;
                else if (changeH > 0) bottomRightY = mouseY + ty;

                w = bottomRightX - tx;
                h = bottomRightY - ty;

                if (0 == w || 0 == h) return;

                var tem:Number;
                if (w < 0)
                {
                    w = -w;
                    changeW = -changeW;
                    tem = tx;
                    tx = bottomRightX;
                    bottomRightX = tem;
                }
                if (h < 0)
                {
                    h = -h;
                    changeH = -changeH;
                    tem = ty;
                    ty = bottomRightY;
                    bottomRightY = tem;
                }

                super.x = tx;
                super.y = ty;
                dispatchEvent(new Event("box_move"));
                resize(w, h);
            }
        }

        // 添加鼠标指针处理器
        private function addMouseCursorHandler():void
        {
            addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
            addEventListener(MouseEvent.ROLL_OUT,  rollOutHandler);
        }
        // 删除鼠标指针处理器
        private function removeMouseCursorHandler():void
        {
            removeEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
            removeEventListener(MouseEvent.ROLL_OUT,  rollOutHandler);
        }

        private function initUI():void
        {
            txt = new TextField();
            txt.wordWrap = false;
            txt.multiline = false;
            txt.width = 100;
            txt.mouseEnabled = false;
            txt.text = " ";
            txt.x = x;
            txt.y = -txt.textHeight;
            addChild(txt);

            hitSprite = new Sprite();
            hitSprite.graphics.beginFill(0, 0);
            hitSprite.graphics.drawRect(0, 0, 10, 10);
            hitSprite.graphics.endFill();
            addChild(hitSprite);

            for (var i:int = 0; i < 8; i++)
            {
                var dot:Dot = new Dot();
                addChild(dot);
                dotList.push(dot);

                // 排列 位置
                dot.lx = i % 3;
                dot.ly = i / 3;
                if (4 == i)
                {
                    dot.lx = 2;
                    dot.ly = 2;
                }
            }
        }
    }
}
import flash.display.Sprite;

// 控制点
class Dot extends Sprite
{

    public var lx:int;
    public var ly:int;

    public function Dot()
    {
        graphics.lineStyle(2, 0xFFFFFF);
        graphics.beginFill(0x0);
        graphics.drawRect( -3, -3, 6, 6);
        graphics.endFill();
        cacheAsBitmap = true
    }
}

示例源码下载☞

标签: , ,

  1. IIYETI | #1

    想实现等比例缩放的开关控制,试着改了一下代码,但总改不好,代码里有些东西我还没能理解,只写成resize(w, w);有BUG,改其他地方结果更糟糕~~,能指点一下吗? :cry:

  2. lite3 | | #2

    @重阳
    我去看了下你的博客,可能是你不懂AS3的语法,所以才看不懂的吧

  3. 重阳 | #3

    我完全看不懂啊 :twisted:

  4. Bindiry | | #4

    赞一个,有空研究下。 :grin:

  1. 本文目前尚无任何 trackbacks 和 pingbacks.
回到顶部