3.3 一颗奔腾的心——基于OpenLayers的地图小工具
目录
3.3
一颗奔腾的心——基于
OpenLayers
的地图小工具
提到小工具,就不得不提到
OpenLayers
。
OpenLayers
(主页是
http://www.openlayers.org
)是由
MetaCarta
最初发起的,用于在网页界面上展示地图的一套
Javascript
脚本框架。
MapGuide
的
Fusion
框架最为核心的地图
Widget
,就是采用了
OpenLayers
框架。
Fusion
框架对
OpenLayers
进行包装,为其添加了更多的功能,从而使之能够更符合
Fusion
框架并与其余
Fusion
组件进行交互。
3.3.1
起名是个学问——术语不一致引发的问题
非常有趣的是,由于
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″ <MapSet <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> |
代码
3-4
布局文件中地图定义的部分代码
其实,
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 |
表
3-2 Fusion
与
OpenLayers
之间的概念映射关系
在阅读
Fusion
和
OpenLayers
的源代码或学习他们的
API
时,一定要注意两者术语上的区别。
本节中,我们提到了
Fusion
引入了地图组这一个概念。这只是
Fusion
对于
OpenLayers
众多改动中的一个。下面我们来看看到底
Fusion
对
OpenLayers
还做了哪些改动。
3.3.2
改头换面——
Fusion
对于
OpenLayers
的改进
为了便于
Fusion
的其他组件能够与地图进行交互,
Fusion
对于
OpenLayers
进行了较为全面的包装。一般来说,如果您不是开发
Fusion.Layers
的开发人员,除了使用一些
OpenLayers
的一些工具性的函数之外,您甚至都不需要知道
OpenLayers
的存在。但是,仅仅进行包装是不够的,由于
OpenLayers
与
Fusion
定位的不同,
Fusion
必须对
OpenLayers
进行扩展才能适应更为复杂的模型。
1.
Fusion
中添加了选择集的概念。
OpenLayers
在同一张地图里面显示多种不同数据源的方面确实做的很好,遗憾的是,它缺少选择集这一至关重要的概念。对于
OpenLayers
来说,选择集完全是可有可无的,因为它的目的在于将地图展示出来,而且,很多地图根本就没有选择集这样的
API
,比如
地图等等。但对于
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
作为右键菜单,再也不需要直接与底层鼠标事件打交道了。
3.3.3
地图标签——地图的定义
前面在介绍
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:
该项表示用什么颜色来显示选中的要素。
了解到了这些信息,
Fusion
就了解该如何加载地图了。
转载自:https://blog.csdn.net/sasyomaru/article/details/5352762