在网上搜了一些例子,找了一大队资料,终于把workFlowEditor做得差不多了,这是一个类似IBM-BPM Editor的工作流编辑器,现还有一些功能没实现,现将部分代码贴在此,有需要的朋友可以交流,拍砖,哈哈。
上图:
节点间的连线重绘:
package com { import flash.geom.Point; public class RefreshLine { /** 和节点相关的线条的数组 **/ public var lineList:Array = []; public var width:Number; public var height:Number; public var lineFlag:LineLag; public var line:Line; public var node:Nodes; private var isFromNode:Boolean=false; private var num1:int=0; //开始节点,箭头右方向,连线数累加 private var num2:int=0; //开始节点,箭头左方向,连线数累加 private var num3:int=0; //开始节点,箭头上方向,连线数累加 private var num4:int=0; //开始节点,箭头下方向,连线数累加 private var numA:int=0; //结束节点,箭头右方向,连线数累加 private var numB:int=0; //结束节点,箭头左方向,连线数累加 private var numC:int=0; //结束节点,箭头上方向,连线数累加 private var numD:int=0; //结束节点,箭头下方向,连线数累加 private var startX:int; private var startY:int; private var endX:int; private var endY:int; public function RefreshLine(node:Nodes) { this.node=node; lineList=node.lineList; } /** * 重绘节点上的连线 * */ public function getAspectArr():void{ for(var j:int = 0; j < lineList.length; j++){ lineFlag = lineList[j]; line = lineFlag.line; switch(line.aspect){ case 1: if(line.fromNode==node) num1++; else numA++; break; case 2: if(line.fromNode==node) num2++; else numB++; break; case 3: if(line.fromNode==node) num3++; else numC++; break; case 4: if(line.fromNode==node) num4++; else numD++; break; } } } public function refreshLine():void{ var isHead:Boolean; var startNO:int=0; //指向开始节点的连线的条数 var endNO:int=0; //指向结束节点的连线的条数 width=node.width; height=node.height; getAspectArr(); for(var i:int = 0; i < lineList.length; i++){ startX = node.x; startY = node.y; endX = node.x; endY = node.y; lineFlag = lineList[i]; line = lineFlag.line; isHead = lineFlag.isHead; if(line.fromNode==node){ isFromNode=true; startNO++; }else{ endNO++; } switch(node.type){ case Nodes.NODE: case Nodes.EMAIL: case Nodes.CLOCK: case Nodes.ENDNODE: circleNodePosition(startNO,endNO); break; case Nodes.RECT: rectNodePosition(startNO,endNO); break; case Nodes.BRECT: rectNodePosition(startNO,endNO); break; case Nodes.DIAMOND: diamondNodePosition(startNO,endNO); break; } /** * 如果是连线箭头所指的,则重设线条开始位置 * 如果不是,则重设连线结束 **/ if(isHead) line.startPoint = new Point(startX,startY); else line.endPoint = new Point(endX,endY); line.drawLine(line.aspect); } num1=0; num2=0; num3=0; num4=0; numA=0; numB=0; numC=0; numD=0; } private function circleNodePosition(startNO:int,endNO:int):void{ switch(line.aspect){ case 1: //箭头向右 switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.CIRCLE_RADIUS*2+1; }else{ startY-=1; } startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO); break; case line.lineStyleArr[2]: startX+=13; startY+=Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO); break; default: startX+=width-15; startY+=Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO); break; } endX+=15; endY+=Nodes.CIRCLE_RADIUS*2/(numA+1)*(endNO); break; case 2: //箭头向左 switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.CIRCLE_RADIUS*2+1; }else{ startY-=1; } startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width-15; startY+=Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO); break; default: startX+=13; startY+=Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO); break; } endX+=width-13; endY+=Nodes.CIRCLE_RADIUS*2/(numB+1)*(endNO); break; case 3: //箭头向上 switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=width-15; }else{ startX+=13; } startY+=Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO); startY+=Nodes.CIRCLE_RADIUS*2+1; break; default: startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO); startY-=1; break; } endX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(numC+1)*(endNO); endY+=Nodes.CIRCLE_RADIUS*2+3; break; case 4: //箭头向下 switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=width-15; }else{ startX+=13; } startY+=Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO); startY-=1; break; default: startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO); startY+=Nodes.CIRCLE_RADIUS*2+1; break; } endX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(numD+1)*(endNO); endY-=2; break; } } private function rectNodePosition(startNO:int,endNO:int):void{ switch(line.aspect){ case 1: switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=height+2; }else{ startY-=0; } startX+=width/(num1+1)*(startNO); break; case line.lineStyleArr[2]: startX-=0; startY+=height/(num1+1)*(startNO); break; default: startX+=width; startY+=height/(num1+1)*(startNO); break; } endX-=2; endY+=height/(numA+1)*(endNO); break; case 2: switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=height+2; }else{ startY-=0; } startX+=width/(num2+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width; startY+=height/(num2+1)*(startNO); break; default: startX-=0; startY+=height/(num2+1)*(startNO); break; } endX+=width+2; endY+=height/(numB+1)*(endNO); break; case 3: switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=width; }else{ startX-=0; } startY+=height/(num3+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/(num3+1)*(startNO); startY+=height+2; break; default: startX+=width/(num3+1)*(startNO); startY-=0; break; } endX+=width/(numC+1)*(endNO); endY+=height+3; break; case 4: switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=width; }else{ startX-=0; } startY+=height/(num4+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/(num4+1)*(startNO); startY-=0; break; default: startX+=width/(num4+1)*(startNO); startY+=height+2; break; } endX+=width/(numD+1)*(endNO); endY-=1; break; } } private function diamondNodePosition(startNO:int,endNO:int):void{ switch(line.aspect){ case 1: if((num1<=1 && line.fromNode==node) || (numA<=1 && line.toNode==node)){ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.DIAMOND_BORDER; }else{ startY-=0; } startX+=width/2; break; case line.lineStyleArr[2]: startX+=4; startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO); break; default: startX+=Nodes.DIAMOND_BORDER+6; startY+=Nodes.DIAMOND_BORDER/2; break; } endX+=3; endY+=Nodes.DIAMOND_BORDER/2; }else{ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.DIAMOND_BORDER-13; }else{ startY+=13; } startX+=width/(num1+1)*(startNO); break; case line.lineStyleArr[2]: startX+=(width-Nodes.DIAMOND_BORDER)/2+10; startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO); break; default: startX+=Nodes.DIAMOND_BORDER-6; startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO); break; } endY+=Nodes.DIAMOND_BORDER/(numA+1)*(endNO); if((num1==3 && startNO==2) || (numA==3 && endNO==2)){ endX+=3; }else{ endX+=15; } } break; case 2: if((num2<=1 && line.fromNode==node) || (numB<=1 && line.toNode==node)){ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.DIAMOND_BORDER; }else{ startY-=0; } startX+=width/2; break; case line.lineStyleArr[2]: startX+=Nodes.DIAMOND_BORDER+6; startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO); break; default: startX+=4; startY+=Nodes.DIAMOND_BORDER/2; break; } endX+=Nodes.DIAMOND_BORDER+6; endY+=Nodes.DIAMOND_BORDER/2; }else{ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.y<line.toNode.y){ startY+=Nodes.DIAMOND_BORDER-13; }else{ startY+=13; } startX+=width/(num2+1)*(startNO); break; case line.lineStyleArr[2]: startX+=Nodes.DIAMOND_BORDER-6; startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO); break; default: startX+=(width-Nodes.DIAMOND_BORDER)/2+13; startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO); break; } endY+=Nodes.DIAMOND_BORDER/(numB+1)*(endNO); if((num2==3 && startNO==2) || (numB==3 && endNO==2)){ endX+=Nodes.DIAMOND_BORDER+7; }else{ endX+=Nodes.DIAMOND_BORDER-4; } } break; case 3: if((num3<=1 && line.fromNode==node) || (numC<=1 && line.toNode==node)){ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=Nodes.DIAMOND_BORDER+6; }else{ startX+=4; } startY+=Nodes.DIAMOND_BORDER/2; break; case line.lineStyleArr[2]: startX+=width/(num3+1)*(startNO); startY+=Nodes.DIAMOND_BORDER; break; default: startX+=width/2; startY-=0; break; } endX+=width/2; endY+=Nodes.DIAMOND_BORDER+2; }else{ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=Nodes.DIAMOND_BORDER-13; }else{ startX+=15; } startY+=Nodes.DIAMOND_BORDER/(num3+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/(num3+1)*(startNO); startY+=Nodes.DIAMOND_BORDER-13; break; default: startX+=width/(num3+1)*(startNO); startY+=13; break; } endX+=width/(numC+1)*(endNO); if((num3==3 && startNO==2) || (numC==3 && endNO==2)){ endY+=Nodes.DIAMOND_BORDER+2; }else{ endY+=Nodes.DIAMOND_BORDER-11; } } break; case 4: if((num4<=1 && line.fromNode==node) || (numD<=1 && line.toNode==node)){ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=Nodes.DIAMOND_BORDER+6; }else{ startX+=4; } startY+=Nodes.DIAMOND_BORDER/2; break; case line.lineStyleArr[2]: startX+=width/(num4+1)*(startNO); startY-=0; break; default: startX+=width/2; startY+=Nodes.DIAMOND_BORDER; break; } endX+=width/2; endY-=1; }else{ switch(line.lineStyle){ case line.lineStyleArr[1]: if(line.fromNode.x<line.toNode.x){ startX+=Nodes.DIAMOND_BORDER-13; }else{ startX+=15; } startY+=Nodes.DIAMOND_BORDER/(num4+1)*(startNO); break; case line.lineStyleArr[2]: startX+=width/(num4+1)*(startNO); startY+=13; break; default: startX+=width/(num4+1)*(startNO); startY+=Nodes.DIAMOND_BORDER-13; break; } endX+=width/(numD+1)*(endNO); if((num4==3 && startNO==2) || (numD==3 && endNO==2)){ endY-=1; }else{ endY+=11; } } break; } } } }
键盘事件类:
package com { import flash.events.KeyboardEvent; import flash.events.MouseEvent; import mx.core.UITextField; import net.L4cd.iTrace; public class WFKeyboard { private var node:Nodes; private var line:Line; private var workFlow:CusWorkFlow; private var o:Object; /** CusWorkFlow对象的放大/缩小参数 **/ private var scaleNO:Number=.2; /** 封装连线的对象 **/ private var lineLag1:LineLag; public var trace:Function = iTrace.init; public function WFKeyboard() { } /** 选择键盘按键ASCII值 **/ public function chooseKey(e:KeyboardEvent,mouseE:MouseEvent):void { o=getObjects(mouseE); node=o.node as Nodes; line=o.line as Line; workFlow=o.workFlow as CusWorkFlow; switch(e.keyCode){ case 8: case 46: deleteNode(node,line,workFlow); break; case 65: if(!e.ctrlKey)return; break; case 107: if(!e.ctrlKey)return; workFlow.scaleX+=scaleNO;//放大CusWorkFlow对象 workFlow.scaleY+=scaleNO; break; case 109: if(!e.ctrlKey)return; workFlow.scaleX-=scaleNO;//缩小CusWorkFlow对象 workFlow.scaleY-=scaleNO; break; } } /** 删除节点或连线 **/ private function deleteNode(node:Nodes,line:Line,workFlow:CusWorkFlow):void { if(!workFlow)return; if(node){ var num:int=node.lineList.length; for(var i:int=0;i<num;i++){ var lineLag:LineLag=node.lineList[i]; workFlow.removeChild(lineLag.line); if(node==lineLag.line.fromNode){ for(var j:int=0;j<lineLag.line.toNode.lineList.length;j++){ lineLag1=lineLag.line.toNode.lineList[j] as LineLag; if(node==lineLag1.line.fromNode){ lineLag.line.toNode.lineList.splice(j,1); } } }else{ for(var k:int=0;k<lineLag.line.fromNode.lineList.length;k++){ lineLag1=lineLag.line.fromNode.lineList[k] as LineLag; if(node==lineLag1.line.toNode){ lineLag.line.fromNode.lineList.splice(k,1); } } } } workFlow.removeChild(node); }else if(line){ for(var m:int=0;m<line.toNode.lineList.length;m++){ lineLag1=line.toNode.lineList[m] as LineLag; if(line==lineLag1.line){ line.toNode.lineList.splice(m,1); break; } } for(var n:int=0;n<line.fromNode.lineList.length;n++){ lineLag1=line.fromNode.lineList[n] as LineLag; if(line==lineLag1.line){ line.fromNode.lineList.splice(n,1); } } workFlow.removeChild(line); } } /** 重画节点边框,表示选中或非选中 **/ public function reDrawNode(map:Nodes):void{ switch(map.type){ case Nodes.NODE: map.drawNode(); break; case Nodes.DOC: map.drawDoc(); break; case Nodes.EMAIL: map.drawEmail(); break; case Nodes.RECT: map.drawRect(); break; case Nodes.BRECT: map.drawBRect(); break; case Nodes.DIAMOND: map.drawDiamond(); break; case Nodes.CLOCK: map.drawClock(); break; case Nodes.ENDNODE: map.drawEndNode(); break; case Nodes.LEFTDASHED: map.drawDashed(); break; case Nodes.RIGHTDASHED: map.drawDashed2(); break; } } /** 返回鼠标选中的对象 **/ private function getObjects(e:MouseEvent):Object{ o=new Object(); if(e.target is UITextField){ o.node=e.target.parent.parent as Nodes; o.workFlow=e.target.parent.parent.parent as CusWorkFlow; }else if(e.target is Nodes){ o.node=e.target as Nodes; o.workFlow=e.target.parent as CusWorkFlow; }else if(e.target is CusWorkFlow){ o.workFlow=e.target as CusWorkFlow; }else if(e.target is Line){ o.line=e.target as Line; o.workFlow=e.target.parent as CusWorkFlow; } return o; } } }
1 楼
tree_161219
2011-03-29
写的很不错呢!
2 楼
debbykindom
2011-09-16
,强大,希望有机会再和兄台深入交流。
3 楼
a0409028
2011-10-19
能不能共享一下,页面源码
4 楼
shlei
2011-10-19
a0409028 写道
能不能共享一下,页面源码
抱歉,这已经是商业产品了,
5 楼
a0409028
2011-11-11
连线是怎么实现的有弧度,据天代码是那块?,感谢 了。
6 楼
shlei
2011-11-11
a0409028 写道
连线是怎么实现的有弧度,据天代码是那块?,感谢 了。
二次贝塞尔曲线,查资料吧,
7 楼
421081646
2012-08-08
挺好的,学习了
8 楼
jcl860
2012-08-30
兄弟, import com.ibm.ilog.elixir.diagram.Graph;缺这些东西啊,这些东西报错了,咋整呢?
9 楼
shlei
2012-08-30
jcl860 写道
兄弟, import com.ibm.ilog.elixir.diagram.Graph;缺这些东西啊,这些东西报错了,咋整呢?
你这个是用的ilog组件,需要导入ilog的swc库文件,
10 楼
jcl860
2012-08-31
兄弟,你有联系方式没有,请给发一下。我的邮箱:317902593@qq.com。
11 楼
shlei
2012-08-31
jcl860 写道
兄弟,你有联系方式没有,请给发一下。我的邮箱:317902593@qq.com。
这里有,自己下载吧,http://www.ibm.com/developerworks/cn/downloads/ws/elixir/
12 楼
jcl860
2012-09-05
兄弟,能把mxml代码贴上看看不,主要是画不出界面啊。
13 楼
jcl860
2012-09-14
兄台:左边面板是图片,还是用mxml画出来的图形?