超炫的业务流程图
前段时间有客户要求做一个动态的业务流程图系统,流程图上需要用有流动的连线效果,连线的流向来表示数据之间的流动。虽然twaver没有提供这种样式的流动效果,但是这个实现起来也不难。先上图:
这张流程图中主要的还是点的流动效果,其他的用twaver实现起来并不难。twaver强大的定制功能,只需要结合美工的图片效果,实现这张图是轻而易举
首先来看看流程图所需的各种矢量图形,比如矩形、圆角矩形、圆、椭圆、多边形等等:
public static const SHAPE_RECTANGLE:String = "rectangle"; public static const SHAPE_OVAL:String = "oval"; public static const SHAPE_ROUNDRECT:String = "roundrect"; public static const SHAPE_STAR:String = "star"; public static const SHAPE_TRIANGLE:String = "triangle"; public static const SHAPE_CIRCLE:String = "circle"; public static const SHAPE_HEXAGON:String = "hexagon"; public static const SHAPE_PENTAGON:String = "pentagon"; public static const SHAPE_DIAMOND:String = "diamond";
而且能设置这些矢量的各种参数,比如线条样式、粗细、颜色、填充颜色、渐变样式、渐变色、3D效果等等:
public static const VECTOR_OUTLINE_PATTERN:String = "vector.outline.pattern"; public static const VECTOR_OUTLINE_WIDTH:String = "vector.outline.width"; public static const VECTOR_OUTLINE_COLOR:String = "vector.outline.color"; public static const VECTOR_FILL_COLOR:String = "vector.fill.color"; public static const VECTOR_GRADIENT:String = "vector.gradient"; public static const VECTOR_GRADIENT_COLOR:String = "vector.gradient.color"; public static const VECTOR_DEEP:String = "vector.deep";
另外TWaver也提供了流程图需要的各种线条样式:
public static const LINK_TYPE_ARC:String = "arc"; public static const LINK_TYPE_TRIANGLE:String = "triangle"; public static const LINK_TYPE_PARALLEL:String = "parallel"; public static const LINK_TYPE_FLEXIONAL:String = "flexional"; public static const LINK_TYPE_FLEXIONAL_HORIZONTAL:String = "flexional.horizontal"; public static const LINK_TYPE_FLEXIONAL_VERTICAL:String = "flexional.vertical"; public static const LINK_TYPE_ORTHOGONAL:String = "orthogonal"; public static const LINK_TYPE_ORTHOGONAL_HORIZONTAL:String = "orthogonal.horizontal"; public static const LINK_TYPE_ORTHOGONAL_VERTICAL:String = "orthogonal.vertical"; public static const LINK_TYPE_HORIZONTAL_VERTICAL:String = "orthogonal.H.V"; public static const LINK_TYPE_VERTICAL_HORIZONTAL:String = "orthogonal.V.H"; public static const LINK_TYPE_EXTEND_TOP:String = "extend.top"; public static const LINK_TYPE_EXTEND_LEFT:String = "extend.left"; public static const LINK_TYPE_EXTEND_BOTTOM:String = "extend.bottom"; public static const LINK_TYPE_EXTEND_RIGHT:String = "extend.right";
而且也能设置线条的箭头样式:
public static const ARROW_FROM:String = "arrow.from"; public static const ARROW_FROM_FILL:String="arrow.from.fill"; public static const ARROW_FROM_ALPHA:String="arrow.from.alpha"; public static const ARROW_FROM_SHAPE:String = "arrow.from.shape"; public static const ARROW_FROM_COLOR:String = "arrow.from.color"; public static const ARROW_FROM_XOFFSET:String = "arrow.from.xoffset"; public static const ARROW_FROM_YOFFSET:String = "arrow.from.yoffset"; public static const ARROW_FROM_WIDTH:String = "arrow.from.width"; public static const ARROW_FROM_HEIGHT:String = "arrow.from.height"; public static const ARROW_FROM_OUTLINE_COLOR:String = "arrow.from.outline.color"; public static const ARROW_FROM_OUTLINE_ALPHA:String = "arrow.from.outline.alpha"; public static const ARROW_FROM_OUTLINE_WIDTH:String = "arrow.from.outline.width"; public static const ARROW_FROM_OUTLINE_PATTERN:String = "arrow.from.outline.pattern"; public static const ARROW_FROM_AT_EDGE:String = "arrow.from.at.edge";
有了这些基本元素后,就可以开始流程图的制作了。这里主要介绍一下如何实现连线的流动和动画效果。基本思路是先起一个Timer,设置连线上闪烁图标的透明度(0-255)以及流动的偏移量(0-100),再重载LinkUI.drawBody,根据图标透明度和流动偏移量重画连线。
private function tick(event:TimerEvent = null):void { iconAlpha -= 40; flowingOffset += 5; if(iconAlpha<0){ iconAlpha = 255; } if(flowingOffset>100){ flowingOffset = 0; } box.forEach(function(element:IElement):void{ if(element is Link){ if(element.getClient("status") != "normal"){ element.setClient("alpha", iconAlpha); }else{ element.setClient("flowingOffset", flowingOffset); } } }); }
override protected function drawBody(g:Graphics):void{ super.drawBody(g); if(link.getClient("status") != "normal"){ var centerPoint:Point = this.network.getPosition( Consts.POSITION_FROM, this, null, this.lineLength/2, 0); if(centerPoint){ var centerX:Number = centerPoint.x; var centerY:Number = centerPoint.y; g.lineStyle(3, 0xFF0000, link.getClient("alpha")/255); g.drawEllipse(centerX-10, centerY-10, 20, 20); var offset:Number = Math.sqrt(10)*2; g.moveTo(centerX-offset, centerY-offset); g.lineTo(centerX+offset, centerY+offset); g.moveTo(0, 0); } }else{ var flowingOffset:Number = link.getClient("flowingOffset"); var position:Point = this.network.getPosition(Consts.POSITION_FROM, this, null, this.lineLength*flowingOffset/100.0, 0); if(position){ var x:Number = position.x; var y:Number = position.y; var linkWidth:Number = link.getStyle(Styles.LINK_WIDTH)+2; g.lineStyle(); g.beginFill(0xFFFFFF, 1); g.drawEllipse(x-linkWidth/2, y-linkWidth/2, linkWidth, linkWidth); g.endFill(); } } }
附件是源代码demo.zip