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>
由于时间原因,网络拓扑图今晚就研究到这里。对于线的样式、动态的从数据库里读取数据来显示节点,对节点的监听。以后慢慢扩展。