[教程]用Flash+XML灵活动态创建一个航空路线图

2007-05-11 23:20 | Army

http://ff9.ffsky.cn/temp\map/Map.rar
简单介绍,基础东西略略而过。
读取xml文件部分不在介绍,重点放在如何解析xml并产生相应的地图上的城市对象,还有画线算法。
xml的格式规定为locations节点中包括每个城市的数据lct节点,因此要添加新的城市信息只需添加lct节点即可。值得注意的是,数据的顺序格式要严格要求,否则将会出现问题。
一个城市数据的格式应该是这样,以“北京”为例:
<lct>
	<id>beijing</id>
	<intro>北京</intro>
	<px>332</px>
	<py>142</py>
	<ix>-10</ix>
	<iy>-25</iy>
	<skyways>
		<terminus>
		<city>shanghai</city>
		<sw>
			<passby>hefei</passby>
			<cp>300|200</cp>
			<passby>shanghai</passby>
			<cp>370|200</cp>
		</sw>
		</terminus>
		<terminus>
		<city>kunming</city>
		<sw>
			<passby>hefei</passby>
			<cp>300|200</cp>
			<passby>kunming</passby>
			<cp>300|300</cp>
		</sw>
		<sw>
			<passby>kunming</passby>
			<cp>200|150</cp>
		</sw>
		</terminus>
		<terminus>
		<city>wulumuqi</city>
		<sw>
			<passby>wulumuqi</passby>
			<cp>250|50</cp>
		</sw>
		</terminus>
	</skyways>
</lct>

其中id是标识地图上产生每个城市对象(即地图上的点)时的名称,intro则是相应的中文名称解释。px和py是这个点的坐标,ix和iy是中文名称的相对坐标(相对于这个点),接着的skyways节点里面则包含所有的以这个城市为起点的航空路线,它比较复杂,接下来慢慢诉说。
skyways里包含不定数量的terminus节点,如其字面意思,每个terminus包含着飞向一个终点站的所有航线信息。
terminus中第一个city节点自然是终点站的id,接下来再次出现不定数量的sw节点,很明显,从这个城市到终点站未必就只有一条路线,可能有多条。不定数量便是这个意思。
接下来sw节点中的节点数量以偶数出现,passby意思是指中途所经历的中转站,紧接着的cp是曲线空值节点的坐标值(这个呆会儿画线时解释),如此知道passby的内容等于终点站的id为止。

画线的思想很简单,利用as的curveTo()方法即可,它接收4个必要参数:曲线控制点x坐标、曲线控制点y坐标、终点x坐标、终点y坐标。在此之前只要设置画线的样式,然后将起点用moveTo()方法移动到相应位置。其中曲线控制点可能会使一些人糊涂:那是什么?
很简单,两点之间是画直线的,设定第三个(非直线上)点便可依次拥有一定弧度,常使用矢量绘图软件的人可能对此有个很好的概念——没错,那就是常说的“切线控制柄”——这个名字读起来可真拗口。

读取xml文件并解析的外部as很简单,无需过多解释:

由于xml文件和解析是在第1帧进行的,而背景中国地图是在第4帧才出现,因此需要将包含城市点的mc的visible设置为false以使它不可见,等到第4帧在设置为true。
你可能疑惑为何地图上的城市点会自动随xml文件的修改而变化?很简单,flash库文件中有个链接名为loc的mc,它就相当于一个类。在上面的as第22行可以看到,每读取一个数据便利用loc这个类创建出一个城市对象。这样不改动flash文件,只需对xml进行删改便能完成一整张中国航空路线地图,感觉很棒吧!
更棒的还在后面。

以下是画线的代码,每当地图上一个城市被鼠标左键点击选中时,这个城市点的onRelease()方法便会激活(第50行),这样初始站就被设置为这个城市点。当鼠标移到其它城市上面时(只是移上去不点击,否则初始站就是点击后的城市了),就会激活那个城市的onRollOver()方法(第9行),这样代码便会搜寻起始站中的二维数组数据,看有没有终点站为鼠标所指的城市,有则开始画曲线。

可能你对画曲线这个地方还是有些难于理解,让我来稍微解释一下吧:
记得xml文件中的skyways节点吗,它包含以这个城市为起点的所有航线数据。在解析xml的as代码中将从起点到某一终点的一条航线按照“终点站名、(中转站名、中转站曲线控制点坐标)*、终点站名、终点站曲线控制点坐标”的格式存为一个数组,然后将所有的数组存为一个二维数组作为这个城市点的属性存在城市的对象中。
需要提示的是,上面那个格式我借用了正则表达式的方式,()*的意思是可能有多个或零个,翻译成可以理解的文字就是可能有不定数量的中转站。另外如果起点到终点的航线有多条的话,每条路线都会存为一个独立的数组而不是合并。

哦,我想我没有什么遗漏了,大致的思想都解释过了,太基本的东西没有说明,因为如果连这些都算上的话,你可能要听上N个小时了……对了对了,我还是解释下那个曲线控制点为何以“300|200”的格式出现吧,|符号是个分隔符,前面是x坐标后面是y坐标,之所以没有将它们分成2个节点是为了节省xml文件长度。毕竟,在程序中用Array对象的split方法是很容易将它提取出来的。
明白了吗?祝你不要被我这些夸夸其辞的语言吓晕~