前面的文章写过如果在MapGuide Studio中为MapGuide添加Google Map、Yahoo Map、Bing Map作为底图,今天就有人给我出了个难题。我知道在MapGuide Fusion Viewer界面上可以用External Provider菜单来切换地图类型,用程序怎么实现呢?
说实话,这个问题我也不会,呵呵。不过经过一番研究还是找到了办法。这里就把我的研究过程写出来供大家参考,以后再遇上类似情况,大家也可以自己来研究了。“授之以渔”吧。
Fusion Viewer和MapGuide Ajax Viewer基本网络布局不太一样,不再采用Ajax Viewer的Frameset的框架模式,而是采用的现在更流行的<Div>+CSS的的布局方式。自然Fusion Viewer的 API自然也有Ajax Viewer基本网络布局的API有所不同。由于Fusion Viewer API里没有公开的方法众多,文档又相对缺乏,估计大家也和我一样,开发过程中常为没有文档而苦恼。首先还是先给大家介绍一下关于Fusion Viewer现有的API,在MapGuide developer Guide里面有一章内容专门介绍了Fusion Viewer的基本API,如果你还没有看过,推荐您首先去看一下,这个文档可以在MapGuide的安装目录下找到。 "C:\Program Files\Autodesk\MapGuideEnterprise2011\WebServerExtensions\Help\DevGuide.pdf"。 如果你以前做过Ajax Viewer基本网络布局开发,肯定想知道AjaxViewer中的API在Fusion Viewer中是否还能不能用,实际上MapGuide Fusion viewer中也提供了一套模拟API,功能和Ajax Viewer API的一致。峻祁连以前也写过相关文章,你可以参考:
Digitize using Fusion Viewer API in MapGuide Enterprise 2011
To Implement ZoomToSelection in Fusion Viewer MapGuide Enterprise 2011
言归正传,现在开始来编程实现底图的切换。首先我想应该有个界面来触发我的程序,这里我新建一个iInvoke Script的自定义命令,命名为SwitchBaseMap,并把他添加到ToolBar上。
下面就开始在Script To invoke框里来写我的实现代码了,当然为了方便编辑,我一般是先在文本编辑器里写好了,再贴进去。怎么写呢?这个需求是切换底图BaseMap,就想Fusion Viewer界面上一样。貌似developer guide文档中没有介绍相关的方法,也许是我忘了,那干脆看Fusion的源码吧。MapGuide的好处就在这里,不知道了就去啃源码 :)
找个好用的文本编辑器,我用notepad++,打开Fusion的源码文件fusionSF.js。这个文件包涵了Fusion的所有相关的东西,位于C:\Program Files\Autodesk\MapGuideEnterprise2011\WebServerExtensions\www\fusion\lib\目录下。同样的目录还有Fusion,js和其他一些分开的js文件,每个文件对应一个模块。我也不太清楚basemap相关的东西放在那个模块下了,干脆就打开这个全的fusionSF.js一通搜。
功夫不负有心人,通过搜索“basemap”关键字,还真让我有所发现,我发现有个函数名叫setBasemap,嘿,这名字不错,貌似就是我要找的东东。
看看他的实现,应该是八九不离十了,上面列出的估计就是可以用的参数了,比如Aerial,Hybrid等等。先试试再说。再往上看一眼,这个setBasemap是Fusion.Widget.BasemapSwitcher类的一个方法,嗯,这下更高兴了。现在看看怎么用这个函数吧。
通过读Developer’s Guide文档,我知道Fusion Viewer中有个全局变量Fusion是老大,找到这个Fusion对象应该就不难找到他下面的小兄弟。如何获取Fusion对象,文档中应该有些示例代码,不过我有点懒,想起来C:\Program Files\Autodesk\MapGuideEnterprise2011\WebServerExtensions\www\fusion\layers\MapGuide\MapGuideViewerApi.js里面已经做过相关的实现了,我就拿过来吧,哈哈! 先alert()测试一下看看Fusion取不取得到。
var mgApiMapWidgetId = 'Map'; var MainFusionWindow = GetFusionWindow(); var OpenLayers = MainFusionWindow.OpenLayers; var Fusion = MainFusionWindow.Fusion; /* locate the Fusion window */ function GetFusionWindow() { var curWindow = window; while (!curWindow.Fusion) { if (curWindow.parent && curWindow != curWindow.parent) { curWindow = curWindow.parent; } else if(curWindow.opener) { curWindow = curWindow.opener; } else { alert('Could not find Fusion instance'); break; } } return curWindow; } function GetFusionMapWidget() { return Fusion.getWidgetById(mgApiMapWidgetId); } alert(Fusion);
经测试没问题,已经成功取到Fusion对象了,下面就是要找这个Fusion.Widget.BasemapSwitcher对象,然后就用他的setBasemap应该就差不多了。怎么找到Fusion.Widget.BasemapSwitcher对象呢?这时我想到了Developer Guide文档上好像说过获取Widget的方法GetWidgetById,实际上前面的代码获取Map的时候也用过了。但是这个BasemapSwitcher的ID是什么呢?找了半天不得其解。算了,不和它耗了,不是还有另外一个很像的方法getWidgetsByType吗?按类型找就可以了。不过需要注意的是同样类型的widget可能有多个,所以这里是返回了一个数组。我的地图上只有一个BasemapSwitcher,所以取第0个就行了。于是有了下面的代码:
var basemapSwitcher = Fusion.getWidgetsByType('BasemapSwitcher')[0]; alert(basemapSwitcher);
通过alert方法测试返回[object],可见已经找到了,然后调用BasemapSwitcher的setBasemap方法就是顺理成章的事了,测试一下,工作正常,哈哈,打完收工。
全部代码就这样,也很简单:
var mgApiMapWidgetId = 'Map'; var MainFusionWindow = GetFusionWindow(); var OpenLayers = MainFusionWindow.OpenLayers; var Fusion = MainFusionWindow.Fusion; /* locate the Fusion window */ function GetFusionWindow() { var curWindow = window; while (!curWindow.Fusion) { if (curWindow.parent && curWindow != curWindow.parent) { curWindow = curWindow.parent; } else if(curWindow.opener) { curWindow = curWindow.opener; } else { alert('Could not find Fusion instance'); break; } } return curWindow; } function GetFusionMapWidget() { return Fusion.getWidgetById(mgApiMapWidgetId); } var basemapSwitcher = Fusion.getWidgetsByType('BasemapSwitcher')[0]; //close base map //basemapSwitcher.setBasemap('None'); // siwth to Bing Map Aerial basemapSwitcher.setBasemap('Aerial');
好了,总之呢,MapGuide Fusion现在是文档简单,但源代码丰富啊,想要什么东西没文档的话,那就源代码里面刨去吧,呵呵。
Cheers,
峻祁连