Flex 学习笔记------ 自定义拖放控件ObjectHandler

Flex 学习笔记------ 自定义拖放控件ObjectHandler

Flex里面写动画效果甚是简单,而且没有兼容性问题,这一点比js好太多了。也是最近学习Flex以来感到令人欣慰的地方。

废话不多说,进入正题。

现在的需求是给定一张图片(或其他控件也可以,暂时我就按自己做的项目上的来举例吧),要求拖动四个角的时候,图片可以按比例缩放。这么一个常见的需求,不用多想,网上肯定已经有现成的控件了不是。google一下,果然,ObjectHandles,这个类库还能支持旋转。功能看那上去很强大,但是,跟我的需求还是有些冲突,我的要求是拖动四个角的时候图片大小按比率缩放,不能拉伸。没关系,没有的东西就自己动手吧,本来也觉得这个功能有点挑战性,正和我意。

那么写之前,简单理一下思路:1),选中一张图片后,四个角上出现可拖动的标志;2)拖动一个角,此时其斜对角为不动点,图片缩放。嗯,看上去主要也就是这么两步。先上效果图吧:

 

 

 

 

 

 

P1P2P3P4围成的是原始图片,拖动P4时,原始图片不动,跟着鼠标缩放的是另一张半透明的图片,当然这张图片是拷贝自原始图片的。

然后,鼠标松开后,图片自动缩放至拖放后的大小。半透明图消失。

 

 

 

 

 

 

 

 

首先第一步,选中图片,绘制四个角的操作按钮。

其实就是绘制四个小矩形而已,方法很简单:

 // 创建句柄,用来拖动和拉伸对象
 private static function createRect():Image {
        var img:Image = new Image();
        var size:int = 10;
        img.graphics.beginFill(0xcf67b9, 0.5);
        img.graphics.drawRect(-size / 2, -size / 2, size, size);
        img.graphics.endFill();
        img.graphics.lineStyle(1, 0);
        img.graphics.drawRect(-size / 2, -size / 2, size, size);
        return img;
}

有了这个方法之后,只要在图片上加上点击事件,第一步就算完成了。直接看效果图:

点击前:               点击后:

第二步:拖动四个角,图片缩放。

方法其实也不难,但需要注意到的是,当拖动一个角的时候,以其对角的点作为当前不动点。比如,在最上面的第一幅图中,拖动P4时,P1为不动点,拖动P2时,P3为不动点,...以此类推。

不就是变换一下不动点嘛,easy,立马就会想到,Flex里面,图片在缩放时是可以设置变换中心的(也就是设置不动点,默认是图片的左上角)。so,开始动手啦:核心功能代码如下

    // 在句柄上按下鼠标左键
    private function rect_mouse_down(e:MouseEvent):void {
        trace("evt_rect_mouse_down");
        currRect = e.currentTarget as Sprite;
        if (!currRect) {
            return;
        }
        container.addEventListener(MouseEvent.MOUSE_MOVE, mouse_move);

        startX = e.stageX;
        startY = e.stageY;

        // 跟随鼠标缩放的操作对象
        displayEl = cloneImage(widget as Image, widget.width, widget.height);
        displayEl.alpha = 0.5;
        displayEl.width = widget.width * widget.scaleX;
        displayEl.height = widget.height * widget.scaleY;
        displayEl.x = rects[0].x;
        displayEl.y = rects[0].y;

        container.addChild(displayEl);

        var index:int = rects.indexOf(currRect);

     // 设置变换不动点 setTransformCenter(displayEl, index); }
// 拖动矩形句柄,鼠标移动 private function mouse_move(e:MouseEvent):void { if (!currRect) { return; } trace("evt_mouse_move"); var moveX:int = e.stageX - startX; var moveY:int = e.stageY - startY; var ind:int = rects.indexOf(currRect); // 正代表放大,负代表缩小 if (ind == 0) { moveX = -moveX; moveY = -moveY; } else if (ind == 1) { moveY = -moveY; } else if (ind == 2) { moveX = -moveX; } deltaScale = Math.max( moveY / widget.height, moveX / widget.width ); displayEl.scaleX = deltaScale / widget.scaleX + 1; displayEl.scaleY = deltaScale / widget.scaleY + 1; } // 在句柄上松开鼠标左键 private function rect_mouse_up(e:MouseEvent):void { trace("rect_mouse_up"); if(!currRect) return; currRect = null; container.removeEventListener(MouseEvent.MOUSE_MOVE, mouse_move); container.removeChild(displayEl); widget.scaleX += deltaScale || 0; widget.scaleY += deltaScale || 0;
     // 重新计算四个角上句柄的位置 setRects(); }

测试之后,出问题了,嗯,忘记设置原图的变换中心了嘛!这样导致拖动任意一个角后,松开鼠标,原图的左上角都不动。不知道各位看官看明白没有,还是截个图说明下吧:

上图中,鼠标拖动P3,不动点是P2,松开鼠标后,应该是P2不动,但实际结果还是P1没动。这样当然不行了,事先还是少考虑了一层啊!。

第三步:鼠标松开后,更新原图的位置。

考虑到以后的重用及可扩展性,这里觉得一次性解决这个问题比较好,而不是每次都要改变图片的变换中心,变来变去,自己都不知道最后的中心在哪了。现在固定变换的中心就是左上角,

指定最后图片显示的位置,让图片正确显示就好。

  private function fixPosition():void{
        var index:int = rects.indexOf(currRect);
        var scale: Number = widget.scaleX + (deltaScale || 0);

        var w:Number = widget.width * scale;
        var h:Number = widget.height * scale;

        var left:Number, top:Number;
        switch (index){
            case 0: // 左上角
                left = rects[3].x - w;
                top = rects[3].y - h;
                break;
            case 1: // 右上角
                left = rects[2].x;
                top = rects[2].y - h;
                break;
            case 2: //  左下角
                left = rects[1].x - w;
                top = rects[1].y;
                break;
            case 3: // 右下角
                left = rects[0].x;
                top = rects[0].y;
                break;
        }
        widget.x = left;
        widget.y = top;
    }

测试一下,嗯,没什么问题!到这里,基本功能就算完成了。当然,这里只是提供一个了基本的思路,这也只是一个最简单的版本,很多项目中的功能还没实现,比如,图片旋转操作,边框不应被放大,图片的平移等。

后面有时间再来补充一下。

测试源码: 这里下载

 

 

posted on 2013-09-15 16:58  花森  阅读(571)  评论(0编辑  收藏  举报