提到小工具,就不得不提到
OpenLayers
。
OpenLayers
(主页是
http://www.openlayers.org
)是由
MetaCarta
最初发起的,用于在网页界面上展示地图的一套
Javascript
脚本框架。
MapGuide
的
Fusion
框架最为核心的地图
Widget
,就是采用了
OpenLayers
框架。
Fusion
框架对
OpenLayers
进行包装,为其添加了更多的功能,从而使之能够更符合
Fusion
框架并与其余
Fusion
组件进行交互。
非常有趣的是,由于
OpenLayers
所采用的术语跟
Fusion
采用的并不是十分一致,甚至
Fusion
不同部分采用的术语也不是十分一致,所以同一个名字在不同地方表达的意思却很可能并不相同。所以,在详细介绍
Fusion
如何对
OpenLayers
进行包装之前,有必要对两者之间的术语进行一下区分,以免当您阅读到相关材料时感到疑惑。
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
时,一定要注意两者术语上的区别。
本节中,我们提到了
Fusion
引入了地图组这一个概念。这只是
Fusion
对于
OpenLayers
众多改动中的一个。下面我们来看看到底
Fusion
对
OpenLayers
还做了哪些改动。
Fusion 对于 OpenLayers 的改进
为了便于 Fusion 的其他组件能够与地图进行交互, Fusion 对于 OpenLayers 进行了较为全面的包装。一般来说,如果您不是开发 Fusion.Layers 的开发人员,除了使用一些 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 这两个事件来通知监听者地图选择集的当前状况。
2. Fusion 开放了更多的事件。借助于 Fusion 自己独立实现的事件机制, Fusion 允许用户接收到更多种类的事件,比如 Session 是否已创建、地图当前忙碌与否、选择集状态变更、当前图层(这个是 Fusion 中的图层,不是 OpenLayers 的)变化等等。
3. Fusion 允许地图的实现类返回自身支持哪些比例尺,这就使得用户可以直观的知道自己当前缩放地图到什么程度。
4. 允许用户随时设置当前地图的背景图片和地图上的光标形状。这对于直观地反应地图当前状态是是否有用的。
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: 该项表示用什么颜色来显示选中的要素。