用到的有三个类,BrokenLine.as,BrokenLineEdge.as,BrokenLineRect.as,效果如图:
当拖到直线后可以折回去。
源码在附件上。有bug的话希望提出来哈。谢谢。
svn地址http://forever-framework.googlecode.com/svn/design/,
箭头效果已经做好了。在svn上。
箭头的制作参照了这位师兄的内容http://zean.iteye.com/blog/1070471
核心类:
package org.forever.view { import flash.events.MouseEvent; import flash.geom.Point; import mx.collections.ArrayList; import mx.core.UIComponent; import mx.logging.ILogger; import mx.logging.Log; import mx.utils.UIDUtil; import spark.components.BorderContainer; import spark.components.SkinnableContainer; /** * 折线的实现(初始化状态是3点两边) */ public class BrokenLine extends UIComponent { private var _app_container:SkinnableContainer; private static var _log:ILogger = Log.getLogger("org.forever.view.BrokenLine"); private var _fromPoint:Point; private var _toPoint:Point; private var _firstRect:BrokenLineRect; private var _secondRect:BrokenLineRect; private var _thirdRect:BrokenLineRect; private var _firstEdge:BrokenLineEdge; private var _rect_w:Number = 6; private var _startMove:Boolean = false; private var _moving:Boolean = false; private var _currentClickRect:BrokenLineRect; private var _rectList:ArrayList; private var _edgeList:ArrayList; public function BrokenLine() { } /**画折线的方法*/ public function draw():void{ initContainer(); _firstRect = new BrokenLineRect(); _secondRect = new BrokenLineRect(); _thirdRect = new BrokenLineRect(); _firstEdge = new BrokenLineEdge(); initFirstRect(); initSecondRect(); initThirdRect(); initFirstEdge(); //建立矩形关联边 _firstRect.secondEdge = _firstEdge; _secondRect.firstEdge = _firstEdge; //建立边关联矩形 _firstEdge.firstRect = _firstRect; _firstEdge.secondRect = _secondRect; //建立矩形关联的矩形 _firstRect.nextRect = _thirdRect; _secondRect.prevRect = _thirdRect; _thirdRect.prevRect = _firstRect; _thirdRect.nextRect = _secondRect; //添加顺序导致组件的重叠z轴顺序 addChild(_firstEdge); addChild(_firstRect); addChild(_thirdRect); addChild(_secondRect); _rectList = new ArrayList(new Array(_firstRect,_thirdRect,_secondRect)); _edgeList = new ArrayList(new Array(_firstEdge)); } /**初始化容器事件*/ public function initContainer():void{ _app_container.addEventListener(MouseEvent.MOUSE_MOVE,appContainerMouseMoveHandler); _app_container.addEventListener(MouseEvent.MOUSE_UP,appContainerMouseUpHandler); } /**获取指定两个矩形的距离,AB=√[(x1-x2)²+(y1-y2)²]*/ public function getDistance(firstRect:BrokenLineRect,secondRect:BrokenLineRect):Number{ return Math.sqrt(Math.pow(firstRect.x - secondRect.x,2) + Math.pow(firstRect.y - secondRect.y,2)); } /**处理拖动180度直线后,去掉左右控制点的方法*/ public function process180():Boolean{ if(_currentClickRect.isSplit){//是拆分过的控制点 var a:Number = getDistance(_currentClickRect,_currentClickRect.prevRect); var b:Number = getDistance(_currentClickRect,_currentClickRect.nextRect); var c:Number = getDistance(_currentClickRect.prevRect,_currentClickRect.nextRect); var cosC:Number=(a*a+b*b-c*c)/(2*a*b); //求出控制点拖动时夹角的及时角度 var acos:Number =(int)(Math.acos(cosC) * 180 / Math.PI); _log.debug("*************角度:"+acos+"**************"); if(_currentClickRect.direction==0 && acos<=165){//第一次将控制点拖动时,角度会逐渐变小,小于165度后确定为正方向 _currentClickRect.direction = 1; _log.debug("*************正方向拖动中**************"); }else if(_currentClickRect.direction==1 && acos>=165){//如果满足正方向拖动后,在往反方向拖动,角度会逐渐变大,大于165度后确定为反方向 _currentClickRect.direction = -1; _log.debug("*************反方向拖动中**************"); } //如果反方向行动,并且角度在指定范围内,去掉前后控制点 if(_currentClickRect.direction==-1 && acos>=176 && acos<=180){ _log.debug("*************进入去掉前后控制点范围**************"); //获取当前控制点矩形的前驱前驱矩形和后继后继矩形 var prevPrevRect:BrokenLineRect = _currentClickRect.prevRect.prevRect; var nextNextRect:BrokenLineRect = _currentClickRect.nextRect.nextRect; //将当前控制点矩形的前驱矩形和后继矩形从容器界面中移除 this.removeChild(_currentClickRect.prevRect); this.removeChild(_currentClickRect.nextRect); //更新各个控制点的关联关系 _currentClickRect.prevRect = prevPrevRect; _currentClickRect.nextRect = nextNextRect; prevPrevRect.nextRect = _currentClickRect; nextNextRect.prevRect = _currentClickRect; //if(prevPrevRect!=_firstRect){//头矩形没有第一条边 //prevPrevRect.firstEdge = _currentClickRect.secondEdge; //} prevPrevRect.secondEdge = _currentClickRect.secondEdge; _currentClickRect.secondEdge.firstRect = prevPrevRect; _currentClickRect.secondEdge.drawLine(); updateRectTop(_currentClickRect.secondEdge); this.removeChild(_currentClickRect.firstEdge); _currentClickRect.firstEdge = null; _currentClickRect.secondEdge = null; _currentClickRect.isSplit = false; _currentClickRect.x = (_currentClickRect.prevRect.x + _currentClickRect.nextRect.x)/2; _currentClickRect.y = (_currentClickRect.prevRect.y + _currentClickRect.nextRect.y)/2; _moving = false; _startMove = false; _currentClickRect.direction = 0; return true; } } return false; } public function appContainerMouseMoveHandler(event:MouseEvent):void{ if(_moving){ _currentClickRect.x = mouseX; _currentClickRect.y = mouseY; if(process180())return; _currentClickRect.refresh(); } } public function appContainerMouseUpHandler(event:MouseEvent):void{ if(_moving && null != _currentClickRect){ _startMove = false; _moving = false; //_log.debug(_currentClickRect.desc + "结束移动......"); } } public function addRectEvent(rect:BrokenLineRect):void{ rect.addEventListener(MouseEvent.MOUSE_DOWN,rectMouseDownHandler); rect.addEventListener(MouseEvent.MOUSE_MOVE,rectMouseMoveHandler); rect.addEventListener(MouseEvent.MOUSE_UP,rectMouseUpHandler); } /**矩形鼠标释放事件,一旦释放,停止拖动*/ public function rectMouseUpHandler(event:MouseEvent):void{ _startMove = false; _moving = false; //_log.debug(_currentClickRect.desc + "结束移动......"); } public function rectMouseDownHandler(event:MouseEvent):void{ _startMove = true;//点击组件做移动准备 _moving = false;//并未真正移动 _currentClickRect = event.currentTarget as BrokenLineRect; _currentClickRect.print(); //_log.debug(_currentClickRect.desc + "被点击,准备开始移动......坐标:x=" + _currentClickRect.x + "y=" + _currentClickRect.y ); } public function rectMouseMoveHandler(event:MouseEvent):void{ if(_startMove && !_moving){//如果准备好移动 //既不是头矩形,也不是尾矩形,也没有拆分过 if(_currentClickRect != _firstRect && _currentClickRect!=_secondRect && !_currentClickRect.isSplit){ var _newRectOne:BrokenLineRect = createRect();//新增第一个控制点矩形 //该矩形是当前控制点矩形和前驱矩形的中间矩形 _newRectOne.x = (_currentClickRect.x + _currentClickRect.prevRect.x)/2; _newRectOne.y = (_currentClickRect.y + _currentClickRect.prevRect.y)/2; _newRectOne.desc = UIDUtil.createUID(); //新增第二个控制点矩形,该矩形是当前控制点矩形和后继矩形的中间矩形 var _newRectTwo:BrokenLineRect = createRect(); _newRectTwo.x = (_currentClickRect.x + _currentClickRect.nextRect.x)/2; _newRectTwo.y = (_currentClickRect.y + _currentClickRect.nextRect.y)/2; _newRectTwo.desc = UIDUtil.createUID(); //获取当前控制点前驱控制点的第二条关联边 var _secondEdge:BrokenLineEdge = _currentClickRect.prevRect.secondEdge; //更新关联边的第一个控制点为当前控制点 _secondEdge.firstRect = _currentClickRect; //更新关联边的第二个控制点为当前控制点的后继控制点 _secondEdge.secondRect = _currentClickRect.nextRect; //更新当前矩形的第二条关联边 _currentClickRect.secondEdge = _secondEdge; //重绘边 _secondEdge.drawLine(); updateRectTop(_secondEdge);//将该边的两端控制点置顶 //新增一条边,建立该节点与前驱节点的边关系 var _newEdge:BrokenLineEdge = new BrokenLineEdge(); _newEdge.firstRect = _currentClickRect.prevRect; _newEdge.secondRect = _currentClickRect; _newEdge.desc = UIDUtil.createUID(); _newEdge.drawLine(); addChild(_newEdge); addChild(_newRectOne); addChild(_newRectTwo); updateRectTop(_newEdge); //更新当前控制点矩形的前驱矩形的关联边为新边 _currentClickRect.prevRect.secondEdge = _newEdge; //更新当前控制点矩形的第一条关联边 _currentClickRect.firstEdge = _newEdge; //更新控制点矩形之间的引用关系 _currentClickRect.prevRect.nextRect = _newRectOne; _currentClickRect.nextRect.prevRect = _newRectTwo; _newRectOne.prevRect = _currentClickRect.prevRect; _newRectOne.nextRect = _currentClickRect; _newRectTwo.prevRect = _currentClickRect; _newRectTwo.nextRect = _currentClickRect.nextRect; _currentClickRect.prevRect = _newRectOne; _currentClickRect.nextRect = _newRectTwo; _currentClickRect.isSplit = true;//标记为已拆分 //添加到集合中 _edgeList.addItem(_newEdge); } _moving = true; _log.debug(_currentClickRect.desc + "移动中......坐标:x=" + _currentClickRect.x + "y=" + _currentClickRect.y); } } /**创建一个新的矩形点*/ public function createRect():BrokenLineRect{ var _newRect:BrokenLineRect = new BrokenLineRect(); _newRect.width = _rect_w; _newRect.height = _rect_w; _newRect.setStyle("borderColor","#70B2EE"); addRectEvent(_newRect); return _newRect; } /**更新指定边的两端矩形置顶*/ public function updateRectTop(_edge:BrokenLineEdge):void{ this.setChildIndex(_edge.firstRect,this.numChildren-1); this.setChildIndex(_edge.secondRect,this.numChildren-1); } /**初始化第一个端点到中点的边*/ public function initFirstEdge():void{ _firstEdge.firstRect = _firstRect; _firstEdge.secondRect = _secondRect; _firstEdge.desc = UIDUtil.createUID(); _firstEdge.drawLine(); } /**初始化中点矩形*/ public function initThirdRect():void{ _thirdRect.width = _rect_w; _thirdRect.height = _rect_w; _thirdRect.setStyle("borderColor","#70B2EE"); _thirdRect.x = (_firstRect.x + _secondRect.x)/2; _thirdRect.y = (_firstRect.y + _secondRect.y)/2; _thirdRect.desc = "_thirdRect"; addRectEvent(_thirdRect); } /**初始化第二个端点的矩形*/ public function initSecondRect():void{ _secondRect.width = _rect_w; _secondRect.height = _rect_w; _secondRect.x = _toPoint.x; _secondRect.y = _toPoint.y - _secondRect.height/2; _secondRect.setStyle("borderColor","#70B2EE"); _secondRect.desc = "_secondRect"; addRectEvent(_secondRect); } /**初始化第一个端点的矩形*/ public function initFirstRect():void{ _firstRect.width = _rect_w; _firstRect.height = _rect_w; _firstRect.x = _fromPoint.x - _firstRect.width; _firstRect.y = _fromPoint.y - _firstRect.height/2; _firstRect.setStyle("borderColor","#70B2EE"); _firstRect.desc = "_firstRect"; addRectEvent(_firstRect); } /******************* get and set ******************/ /**线终点*/ public function get toPoint():Point { return _toPoint; } /** * @private */ public function set toPoint(value:Point):void { _toPoint = value; } /**线起点*/ public function get fromPoint():Point { return _fromPoint; } /** * @private */ public function set fromPoint(value:Point):void { _fromPoint = value; } /**显示所有可变组件的容器*/ public function get app_container():SkinnableContainer { return _app_container; } /** * @private */ public function set app_container(value:SkinnableContainer):void { _app_container = value; } public function get moving():Boolean { return _moving; } public function set moving(value:Boolean):void { _moving = value; } } }
辅助类:
package org.forever.view { import flash.events.MouseEvent; import flash.geom.Point; import mx.core.UIComponent; import mx.logging.ILogger; import mx.logging.Log; /**折线用的线条边类*/ public class BrokenLineEdge extends UIComponent { private static var _log:ILogger = Log.getLogger("org.forever.view.BrokenLineEdge"); private var _fromPoint:Point; private var _toPoint:Point; private var _lineColor:uint=0x000000; private var _thickness:Number = 1; private var _alpha:Number = 1; private var _firstRect:BrokenLineRect; private var _secondRect:BrokenLineRect; private var _desc:String; public function BrokenLineEdge() { super(); _fromPoint = new Point(); _toPoint = new Point(); addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler); } public function mouseDownHandler(e:MouseEvent):void{ print(); } public function print():void{ _log.debug("*******************("+_desc+")信息************************************"); _log.debug("第一个端点矩形:"+_firstRect.desc); _log.debug("第二个端点矩形:"+_secondRect.desc); _log.debug("*********************************************************************"); } /**绘制线条*/ public function drawLine():void{ _log.debug("重绘边" + _desc + ";" + _firstRect.desc + ":" + _secondRect.desc); fromPoint.x = _firstRect.x + _firstRect.width/2; fromPoint.y = _firstRect.y + _firstRect.height/2; toPoint.x = _secondRect.x+_secondRect.width/2; toPoint.y = _secondRect.y + _secondRect.height/2; this.graphics.clear(); this.graphics.lineStyle(_thickness,_lineColor,_alpha); this.graphics.moveTo(_fromPoint.x,_fromPoint.y); this.graphics.lineTo(_toPoint.x,_toPoint.y); } /**线起点*/ public function get fromPoint():Point { return _fromPoint; } /** * @private */ public function set fromPoint(value:Point):void { _fromPoint = value; } /**线终点*/ public function get toPoint():Point { return _toPoint; } /** * @private */ public function set toPoint(value:Point):void { _toPoint = value; } /**线条颜色*/ public function get lineColor():uint { return _lineColor; } /** * @private */ public function set lineColor(value:uint):void { _lineColor = value; } /**关联的第一个端点*/ public function get firstRect():BrokenLineRect { return _firstRect; } /** * @private */ public function set firstRect(value:BrokenLineRect):void { _firstRect = value; } /**关联的第二个端点*/ public function get secondRect():BrokenLineRect { return _secondRect; } /** * @private */ public function set secondRect(value:BrokenLineRect):void { _secondRect = value; } public function get desc():String { return _desc; } public function set desc(value:String):void { _desc = value; } } }
控制点类:
package org.forever.view { import flash.events.MouseEvent; import mx.logging.ILogger; import mx.logging.Log; import spark.components.BorderContainer; /**折线用到的矩形点类*/ public class BrokenLineRect extends BorderContainer { private static var _log:ILogger = Log.getLogger("org.forever.view.BrokenLineRect"); private var _firstEdge:BrokenLineEdge; private var _secondEdge:BrokenLineEdge; private var _prevRect:BrokenLineRect; private var _nextRect:BrokenLineRect; private var _isSplit:Boolean = false; private var _rect_w:Number = 6; private var _count:Number = 0; private var _direction:Number = 0; private var _desc:String; public function BrokenLineRect() { } public function print():void{ _log.debug("*******************("+_desc+")信息************************************"); _log.debug("前驱矩形:" + (_prevRect!=null?_prevRect.desc:"没有前驱矩形")); _log.debug("后继矩形:" + (_nextRect!=null? _nextRect.desc:"没有后继矩形")); _log.debug("第一条关联边:" + (_firstEdge!=null? _firstEdge.desc:"没有第一条关联边")); _log.debug("第二条关联边:" + (_secondEdge!=null? _secondEdge.desc:"没有第二条关联边")); _log.debug("*********************************************************************"); } public function refresh():void{ updateFirstEdgePosition(); updateSecondEdgePosition(); updateNextRectPosition(); updatePrevRectPosition(); } /**更新第二条边的位置*/ public function updateSecondEdgePosition():void{ if(_secondEdge != null){ _secondEdge.drawLine(); } } /**更新后继矩形的位置*/ public function updateNextRectPosition():void{ if(_nextRect != null && _nextRect.nextRect != null){ _nextRect.x = (x + _nextRect.nextRect.x)/2; _nextRect.y = (y + _nextRect.nextRect.y)/2; } } /**更新前驱矩形的位置*/ public function updatePrevRectPosition():void{ if(_prevRect != null && _prevRect.prevRect != null){ _prevRect.x = (x + _prevRect.prevRect.x)/2; _prevRect.y = (y + _prevRect.prevRect.y)/2; } } /**更新第一条边的位置*/ public function updateFirstEdgePosition():void{ if(_firstEdge != null){ _firstEdge.drawLine(); } } public function updateFirstEdge():void{ if(_firstEdge != null ){ } } /**矩形关联的第一条边(左边)*/ public function get firstEdge():BrokenLineEdge { return _firstEdge; } /** * @private */ public function set firstEdge(value:BrokenLineEdge):void { _firstEdge = value; } /**矩形关联的第二条边(右边)*/ public function get secondEdge():BrokenLineEdge { return _secondEdge; } /** * @private */ public function set secondEdge(value:BrokenLineEdge):void { _secondEdge = value; } /**前驱矩形节点*/ public function get prevRect():BrokenLineRect { return _prevRect; } /** * @private */ public function set prevRect(value:BrokenLineRect):void { _prevRect = value; } /**后继矩形节点*/ public function get nextRect():BrokenLineRect { return _nextRect; } /** * @private */ public function set nextRect(value:BrokenLineRect):void { _nextRect = value; } /**是否拆分过,即创建了该矩形与前驱(后继)矩形的中点矩形*/ public function get isSplit():Boolean { return _isSplit; } /** * @private */ public function set isSplit(value:Boolean):void { _isSplit = value; } public function get desc():String { return _desc; } public function set desc(value:String):void { _desc = value; } /**拖动方向,0未初始化,1正方向,-1反方向*/ public function get direction():Number { return _direction; } /** * @private */ public function set direction(value:Number):void { _direction = value; } } }