Flex里面写动画效果甚是简单,并且没有兼容性问题,这一点比js好太多了。也是最近学习Flex以来感到使人欣慰的地方。学习
废话很少说,进入正题。测试
如今的需求是给定一张图片(或其余控件也能够,暂时我就按本身作的项目上的来举例吧),要求拖动四个角的时候,图片能够按比例缩放。这么一个常见的需求,不用多想,网上确定已经有现成的控件了不是。google一下,果真,ObjectHandles,这个类库还能支持旋转。功能看那上去很强大,可是,跟个人需求仍是有些冲突,个人要求是拖动四个角的时候图片大小按比率缩放,不能拉伸。不要紧,没有的东西就本身动手吧,原本也以为这个功能有点挑战性,正和我意。动画
那么写以前,简单理一下思路:1),选中一张图片后,四个角上出现可拖动的标志;2)拖动一个角,此时其斜对角为不动点,图片缩放。嗯,看上去主要也就是这么两步。先上效果图吧:google
P1P2P3P4围成的是原始图片,拖动P4时,原始图片不动,跟着鼠标缩放的是另外一张半透明的图片,固然这张图片是拷贝自原始图片的。spa
而后,鼠标松开后,图片自动缩放至拖放后的大小。半透明图消失。code
其实就是绘制四个小矩形而已,方法很简单:orm
// 建立句柄,用来拖动和拉伸对象 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; }
有了这个方法以后,只要在图片上加上点击事件,第一步就算完成了。直接看效果图:对象
点击前: 点击后:
blog
方法其实也不难,但须要注意到的是,当拖动一个角的时候,以其对角的点做为当前不动点。好比,在最上面的第一幅图中,拖动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; }
测试一下,嗯,没什么问题!到这里,基本功能就算完成了。固然,这里只是提供一个了基本的思路,这也只是一个最简单的版本,不少项目中的功能还没实现,好比,图片旋转操做,边框不该被放大,图片的平移等。
后面有时间再来补充一下。
测试源码: 这里下载