提到小工具,就不得不提到
OpenLayers
。
OpenLayers
(主頁是
http://www.openlayers.org
)是由
MetaCarta
最初發(fā)起的,用于在網頁界面上展示地圖的一套
Javascript
腳本框架。
MapGuide
的
Fusion
框架最為核心的地圖
Widget
,就是采用了
OpenLayers
框架。
Fusion
框架對
OpenLayers
進行包裝,為其添加了更多的功能,從而使之能夠更符合
Fusion
框架并與其余
Fusion
組件進行交互。
非常有趣的是,由于
OpenLayers
所采用的術語跟
Fusion
采用的并不是十分一致,甚至
Fusion
不同部分采用的術語也不是十分一致,所以同一個名字在不同地方表達的意思卻很可能并不相同。所以,在詳細介紹
Fusion
如何對
OpenLayers
進行包裝之前,有必要對兩者之間的術語進行一下區(qū)分,以免當您閱讀到相關材料時感到疑惑。
OpenLayers
認為,用戶看到的由多個圖層
(layer)
組成的一張地圖
(map)
。地圖本身與加載的數據源格式無關,與數據源格式相關的是圖層。因此,地圖類只有一個(
OpenLayers.Map
),而圖層類卻有很多,這些類都以
OpenLayers.Layer
作為命名空間,如
OpenLayers.Layer.Google/Yahoo/MapGuide/WMS/Vector
等等。
這樣的結構有一個問題,那就是所有的圖層之間是平行的關系,這是很不利于圖層管理的。我們假設有這樣一張地圖:該地圖包含有十二個圖層,有九個來自于不同數據源的圖層和三個位于頂層的
Vector
層。那么,我如果想用代碼去處理所有
Vector
的層,就必須遍歷所有的層,依次比較是不是
Vector
層,再對
Vector
層進行處理。解決這個問題的方案很簡單,那就是引入層級結構,允許用戶把圖層分組。比如上面的例子中,把三個
Vector
分成一組,比如命名為“標記”組,屆時只需要對標記組中的每一個層進行處理即可。
這也正是
Fusion
對于
OpenLayers
眾多改進中的一個。而問題也正是這里引入的:地圖
Widget
在給這種層級結構命名的時候,出人意料地采用了另外的命名方式:地圖
Widget
把圖層組命名為“地圖組”
(map group)
,把組里面的圖層命名為
(map)
。下面代碼是示例數據中
Library://Samples/Sheboygan/FlexibleLayouts/Slate.ApplicationDefinition
布局文件對于地圖定義的那一部分,用戶可以在
MapGuide Studio
中通過點擊位于
Map
面板上的
“Edit Map Group”
按鈕來查看這部分內容。
<?xml version="1.0" encoding="utf-8"?>
<MapSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
? <MapGroupType id="Sheboygan">
??? <Map>
????? <Type>MapGuide</Type>
????? <SingleTile>true</SingleTile>
????? <Extension>
??????? <ResourceId>Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition</ResourceId>
??????? <SelectionAsOverlay>true</SelectionAsOverlay>
??????? <SelectionColor>0x0000FFA0</SelectionColor>
????? </Extension>
??? </Map>
??? <Extension />
? </MapGroupType>
</MapSet>
|
布局文件中地圖定義的部分代碼
其實,
MapGuide
這樣做是有原因的。這個問題源于不同產品之間定位的不同:
OpenLayers
框架的目的是在同一張地圖上面顯示多個數據源。所以在
OpenLayers
看來,一個來自
MapGuide
的地圖僅僅是一個層而已。然而,在
MapGuide
內部,一張
MapGuide
地圖內是包含多個
Layer
,具體表現就是一個
MapDefinition
里可以包含多個
LayerDefinition
。所以,如果
Fusion
把
MapGuide
叫做一個
Layer
的話,又該如何稱呼里面的
Layer
呢?
鑒于這樣的考慮,
Fusion
才做了這種概念上的映射:
Fusion
中的地圖
Widget
對應
OpenLayers
里面的地圖;
Fusion
里面的地圖組是一個邏輯概念,從而形成一種邏輯上的層級結構以便管理;
Fusion
中的地圖實際對應于
OpenLayers
里面的圖層。
但事情到這里還沒有結束,接下來的事情可能會讓您有些意外:在編寫地圖
Widget
實現代碼時,為了能夠便于與
OpenLayers
中的類對應起來,
Fusion
將地圖(也就是
OpenLayers
中的圖層)稱為
Layers
(注意,不是
Layer
),并要求每一個地圖的代碼都繼承自
Fusion.Layers
。比如,
MapGuide
的
Layers
的名稱就叫做
Fusion.Layers.MapGuide
。
下表總結了
Fusion
與
OpenLayers
之間這種概念映射關系
Fusion
概念
|
Fusion
代碼命名
|
OpenLayers
概念
|
OpenLayers
代碼命名
|
地圖
|
Fusion.Layers
|
圖層
|
OpenLayers.Layer
|
地圖組
|
|
無對應概念
|
|
地圖
Widget
|
Fusion.Widget.Map
|
地圖
|
OpenLayers.Map
|
?Fusion
與
OpenLayers
之間的概念映射關系
在閱讀
Fusion
和
OpenLayers
的源代碼或學習他們的
API
時,一定要注意兩者術語上的區(qū)別。
本節(jié)中,我們提到了
Fusion
引入了地圖組這一個概念。這只是
Fusion
對于
OpenLayers
眾多改動中的一個。下面我們來看看到底
Fusion
對
OpenLayers
還做了哪些改動。
Fusion 對于 OpenLayers 的改進
為了便于 Fusion 的其他組件能夠與地圖進行交互, Fusion 對于 OpenLayers 進行了較為全面的包裝。一般來說,如果您不是開發(fā) Fusion.Layers 的開發(fā)人員,除了使用一些 OpenLayers 的一些工具性的函數之外,您甚至都不需要知道 OpenLayers 的存在。但是,僅僅進行包裝是不夠的,由于 OpenLayers 與 Fusion 定位的不同, Fusion 必須對 OpenLayers 進行擴展才能適應更為復雜的模型。
1.?????? Fusion 中添加了選擇集的概念。 OpenLayers 在同一張地圖里面顯示多種不同數據源的方面確實做的很好,遺憾的是,它缺少選擇集這一至關重要的概念。對于 OpenLayers 來說,選擇集完全是可有可無的,因為它的目的在于將地圖展示出來,而且,很多地圖根本就沒有選擇集這樣的 API ,比如 Google 地圖等等。但對于 Fusion 則不同,我們很難想象沒有選擇集,用戶該如何利用 MapGuide 進行管理。所以, Fusion 加入了選擇集這個概念,并且要求實現 Layers 的地圖(比如 MapGuide )實現選擇集功能。我們可以看到, Fusion.Widget.Map 中不但有諸如 get/set/clear/hasSelection 這樣控制和讀取選擇集的函數,而且有 MAP_SELECTION_ON 和 MAP_SELECTION_OFF 這兩個事件來通知監(jiān)聽者地圖選擇集的當前狀況。
2.?????? Fusion 開放了更多的事件。借助于 Fusion 自己獨立實現的事件機制, Fusion 允許用戶接收到更多種類的事件,比如 Session 是否已創(chuàng)建、地圖當前忙碌與否、選擇集狀態(tài)變更、當前圖層(這個是 Fusion 中的圖層,不是 OpenLayers 的)變化等等。
3.?????? Fusion 允許地圖的實現類返回自身支持哪些比例尺,這就使得用戶可以直觀的知道自己當前縮放地圖到什么程度。
4.?????? 允許用戶隨時設置當前地圖的背景圖片和地圖上的光標形狀。這對于直觀地反應地圖當前狀態(tài)是是否有用的。
5.?????? 支持右鍵菜單。雖然在瀏覽器上實現右鍵菜單相對簡單一些,但是通過使用地圖 Widget 的 setContextMenu ,代碼編寫者就可以直接把已經準備好的 div 作為右鍵菜單,再也不需要直接與底層鼠標事件打交道了。
地圖的定義
前面在介紹 Fusion 與 OpenLayers 術語不同的時候,摘錄了應用程序定義中對于地圖部分的定義。通過解析這個定義, Fusion 了解了應該如何加載該地圖。下面,我們就來看看這個定義中到底都定義了哪些東西。
在 Fusion 中,一個地圖組用一個 MapGroup 進行標簽定義, MapGroup 里面的 Map 標簽就是對于一個地圖的定義了。
1.?????? Type: 該標簽標示了地圖的類型。所有 MapGuide 地圖該標簽的值均為 MapGuide 。當 Fusion 讀取到該地圖的 Type 時,就會用對應的 “Fusion.Layers. 標簽值 ” 來初始化該地圖。比如 MapGuide 地圖就會用 Fusion.Layer.MapGuide 來初始化。
2.?????? SingleTile: 如果該項為真,則表示該項不采用分塊服務。
3.?????? Extension: 該于擴展 Map 標簽,來為地圖初始化提供更多的信息。各個 Fusion.Layers 的實現類可以自行決定其需要的內容,以及如何解釋這些內容。對于 MapGuide 而言,有以下常見的擴展:
a)???????? ResourceId: MapDefinition 的資源 Id ,通過該 Id , Fusion 可以知道加載哪一個地圖定義。
b)??????? SelectionAsOverLay: 如果該項是 true ,那么將會使用 GETDYNAMICOVERLAY 來獲取地圖,否則采用 GETMAPIMAGE 來獲取地圖。前者是新版本才支持的,可以把選擇集和地圖本身繪制成兩張地圖。如果您使用的 MapGuide 版本比較舊,您可以把該項設置成為 false
c)???????? SelectionColor: 該項表示用什么顏色來顯示選中的要素。