Birdeye绘制网络拓扑图Demo
学习flex有一周了,晚上一边学习Ravis,一边实践着写个demo记录一下自己学习的足迹。第一次写博客,如有什么不对,欢迎讨论。此demo采用Flex开源组件Birdeye中的关系型图表(Ravis),
因为比较适合我这种对flash构图能力有限,但能写写代码的菜鸟。
一、直接上效果图
二、项目的目录结构:
三.需要的测试datasource data/graph.xml
1 <Graph> 2 <Node id="1" name="Switch" desc="This is a Switch" nodeSize="40" nodeClass="earth" nodeIcon="swtich" /> 3 <Node id="2" name="computerA" nodeSize="40" nodeClass="tree" nodeIcon="computer" /> 4 <Node id="3" name="computerB" nodeSize="40" nodeClass="tree" nodeIcon="computer"" /> 5 <Node id="4" name="computerC" nodeSize="40" nodeClass="tree" nodeIcon="computer" /> 6 <Node id="5" name="computerD" nodeSize="40" nodeClass="tree" nodeIcon="computer" /> 7 <Node id="6" name="computerE" nodeSize="40" nodeClass="tree" nodeIcon="computer" /> 8 <Node id="7" name="computerF" nodeSize="40" nodeClass="tree" nodeIcon="computer" /> 9 <Edge fromID="1" toID="2" edgeLabel="No Change" flow="50" color="0x556b2f" edgeClass="sun" edgeIcon="NoChange" /> 10 <Edge fromID="1" toID="3" edgeLabel="Bad" flow="400" color="0xcd5c5c" edgeClass="sun" edgeIcon="Bad" /> 11 <Edge fromID="1" toID="4" edgeLabel="Good" flow="80" color="0xb22222" edgeClass="sun" edgeIcon="Good" /> 12 <Edge fromID="1" toID="5" edgeLabel="Good" flow="100" color="0x607b8b" edgeClass="sun" edgeIcon="Good" /> 13 <Edge fromID="1" toID="6" edgeLabel="No Change" flow="120" color="0x333333" edgeClass="sun" edgeIcon="NoChange" /> 14 <Edge fromID="1" toID="7" edgeLabel="Bad" flow="150" color="0x6b8e23" edgeClass="sun" edgeIcon="Bad" /> 15 16 </Graph>
datasource的简单说明:(首次看略过) nodeClass:节点样式 nodeIcon:节点的图标,这个节点要显示图标必须在指明VisualGraph的呈示器为:IconNodeRenderer
eg:itemRenderer="org.un.cava.birdeye.ravis.components.renderers.nodes.IconNodeRenderer"
这个还不够,我们需要让人renderer知道我们所要加载的图片在哪里?通过查看源码发现,在IconNodeRenderer.as这个类里是这样对图片渲染的:
img = RendererIconFactory.createIcon(this.data.data.@nodeIcon,32);
再往上跟踪: icon = EmbeddedIcons.generateImage(suffix,size);
打开EmdeddedIcons.as这个类,恍然大悟,原来在datasource中的 nodeIcon="10",这个10是图片的别名,工作原理是这样的:
[Bindable] [Embed(source="nodes/10.png")] static public var n10Icon:Class; public static function generateImage(type:String, size:int = 32):Image { var img:Image = new Image(); img.width = size; img.height = size; switch(type) { case "10": img.source = EmbeddedIcons.n10Icon; break; ..... } return img; }
为了熟悉源码,我修改了这个源码,把自己找的两张图片放到:org.un.cava.birdeye.ravis/assets/icons文件夹下,并加上对自己的图片的注入,这样就可以显示我们自定义的图片了,修改后的源码为:
/** * 扩展 * **/ [Bindable] [Embed(source="nodes/my_switch.png")] static public var swtichIcon:Class; [Bindable] [Embed(source="nodes/my_computer.png")] static public var computerIcon:Class; ......................... switch(type) { case "swtich": img.source=EmbeddedIcons.swtichIcon; break; case "computer": img.source=EmbeddedIcons.computerIcon; break; case "ravis": img.source = EmbeddedIcons.ravisIcon; break; .................
四. 主程序: network.mxml 为了简单为这里没有使用MVC
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:layouterControls="org.un.cava.birdeye.ravis.components.ui.controls.layouterControls.*" xmlns:vgraphControls="org.un.cava.birdeye.ravis.components.ui.controls.vgraphControls.*" xmlns:ravis="org.un.cava.birdeye.ravis.graphLayout.visual.*" creationComplete="init()" > <fx:Script> <![CDATA[ import org.un.cava.birdeye.ravis.graphLayout.data.Graph; import org.un.cava.birdeye.ravis.graphLayout.data.IGraph; import org.un.cava.birdeye.ravis.graphLayout.layout.HierarchicalLayouter; import org.un.cava.birdeye.ravis.graphLayout.layout.ILayoutAlgorithm; import org.un.cava.birdeye.ravis.graphLayout.visual.IEdgeRenderer; import org.un.cava.birdeye.ravis.graphLayout.visual.IVisualNode; import org.un.cava.birdeye.ravis.graphLayout.visual.edgeRenderers.BaseEdgeRenderer; private var graph:IGraph;//图表Graph对象 private var layouter:ILayoutAlgorithm;//布局对象,对所有的vgraph private var selectedEdgeRenderer:IEdgeRenderer;//连线方式 private var startRoot:IVisualNode; private static var xmlData:XML; private function init():void { /*一、加载xml文件
*/
var url:URLRequest=new URLRequest("data/graph.xml"); //创建URLLoader对象。 var loader:URLLoader=new URLLoader(); /** * 为新创建的对象注册事件监听, * 我们需要监听的是Event.COMPLETE事件,如果xml load完成调用 onComplete函数。 * **/ loader.addEventListener(Event.COMPLETE,onComplete) /*** * * 3.调用load()函数,只有调用load函数加载完成后才会发生onComplete函数 * * **/ loader.load(url); } /*** * * 事件处理函数onComplete * * * */ public function onComplete(event:Event):void{ /** * 下来的问题就是怎么得到取到的xml数据了。 * 首先把onComplete函数的参数event的target属性转换成URLLoader对象 * 注意flex中的强制类型转化有别于java * **/ var result:URLLoader=URLLoader(event.target); /** * 然后再把这个对象的data属性转换成xml对象 * **/ xmlData=XML(result.data);
/*** * 二、绘制Graph * 1.创建IGraph对象,用来组织数据结构 * */ this.graph=new Graph("graphId",false,xmlData); /*** * 2.把Graph这个数据结构给VisualGraph这个显示器 * */ vgraph.graph=graph; /*** * 3.创建布局对象,这里创建的布局类型为tree,并设置自动适应屏幕来展开 * */ this.layouter=new HierarchicalLayouter(vgraph); layouter.autoFitEnabled=true;// automatically fit the layout to the screen /** * 4.把这个布局对象set给二维矢量绘图工具 * **/ this.vgraph.layouter=this.layouter; // //this.vgraph.edgeRendererFactory=new ClassFactory(BaseEdgeRenderer); /** * * **/ vgraph.maxVisibleDistance =2; /** *从load过来的数据中通过ID来查找节点id为 1的节点,并赋值为startRoot
* **/ startRoot = this.graph.nodeByStringId("1").vnode; vgraph.displayEdgeLabels =false;
/** *指定root节点
* ** vgraph.currentRootVNode = startRoot; // vgraph.draw(); } ]]> </fx:Script> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <s:Panel width="100%" height="100%" horizontalCenter="center" borderColor="#CCCCCC"> <!--Group标签管理其他可视组件--> <s:Group id="graphGroup" width="100%" height="100%" > <ravis:VisualGraph id="vgraph" width="100%" height="100%" left="0" right="0" top="0" bottom="5" backgroundColor="#FFFFFF" alpha="1" itemRenderer="org.un.cava.birdeye.ravis.components.renderers.nodes.IconNodeRenderer" edgeLabelRenderer="org.un.cava.birdeye.ravis.components.renderers.edgeLabels.BaseEdgeLabelRenderer" visibilityLimitActive="true" /> </s:Group> </s:Panel> </s:Application>
由于时间原因,网络拓扑图今晚就研究到这里。对于线的样式、动态的从数据库里读取数据来显示节点,对节点的监听。以后慢慢扩展。