静态地图及应用
此处说的静态地图指没有经过地理投影什么的普通地图,比如一些规划图,室内建筑图,平面示意图等等,这些图一般都不会很大,但常用于一些演示系统中。 会涉及到一些简单的定位,标注等。 OpenLayers 3也充分考虑到了这样的需求,提供了对应的source
类: ol.source.ImageStatic
。 示例请看下面这个地图,显示的是成都熊猫基地的平面图:
因为应用于OpenLayers 3中,所以地图可以放大缩小,具备相应的功能,对于演示而言,无疑加快了开发效率。 对应的代码如下:
<div id="map" style="width: 100%"></div>
<script type="text/javascript">
// 地图设置中心,设置到成都,在本地离线地图 offlineMapTiles刚好有一张zoom为4的成都瓦片
var center = ol.proj.transform([104.06667, 30.66667], 'EPSG:4326', 'EPSG:3857');
// 计算熊猫基地地图映射到地图上的范围,图片像素为 550*344,保持比例的情况下,把分辨率放大一些
var extent = [center[0]- 550*1000/2, center[1]-344*1000/2, center[0]+550*1000/2, center[1]+344*1000/2];
//创建地图
var map = new ol.Map({
view: new ol.View({
center: center,
zoom: 7
}),
target: 'map'
});
// 加载熊猫基地静态地图层
map.addLayer(new ol.layer.Image({
source: new ol.source.ImageStatic({
url: '../img/pandaBase.jpg', // 熊猫基地地图
imageExtent: extent // 映射到地图的范围
})
}));
</script>
代码中有详细注释,可帮助理解,要应用静态地图,需要注意设置图片在地图中占据的extent
。 如果没有这个设置,图片就不能和位置关联在一起,也就不能应用于OpenLayers 3中。 大家肯定非常关心extent
的计算[center[0]- 550*1000/2, center[1]-344*1000/2, center[0]+550*1000/2, center[1]+344*1000/2]
,为什么这样计算? 这个地方我想让图片本身的大小和地理范围产生联系,图片的大小为550*344像素,在此基础上同比放大1000倍,作地理范围。当然也可以不用放大,直接作为地理范围,只是这样需要放大地图到很高的层级才能看到它。 有了这样的映射关系后,图片能保持长宽比不变,从而不变形。 为什么引入center
,除以2相关的计算? 这是一个简单计算,目的在于设置图片显示在地图中心。
把地图加载出来只是第一步,我们最重要的是在地图上定位,并处理相应的业务。比如我们希望在图片[390,145]像素位置添加一个活动图标表示这个地方有现场活动,就像下面这样:
看到地图上的小旗帜没有,它就是新加上去的活动图标。 那么我们是如何做到的呢:
<div id="map2" style="width: 100%"></div>
<script type="text/javascript">
// 地图设置中心,设置到成都,在本地离线地图 offlineMapTiles刚好有一张zoom为4的成都瓦片
var center2 = ol.proj.transform([104.06667, 30.66667], 'EPSG:4326', 'EPSG:3857');
// 计算熊猫基地地图映射到地图上的范围,图片像素为 550*344,保持比例的情况下,把分辨率放大一些
var extent2 = [center[0]- 550*1000/2, center[1]-344*1000/2, center[0]+550*1000/2, center[1]+344*1000/2];
//创建地图
var map2 = new ol.Map({
view: new ol.View({
center: center,
zoom: 7
}),
target: 'map2'
});
// 加载熊猫基地静态地图层
map2.addLayer(new ol.layer.Image({
source: new ol.source.ImageStatic({
url: '../img/pandaBase.jpg', // 熊猫基地地图
imageExtent: extent2 // 映射到地图的范围
})
}));
// 创建一个用于放置活动图标的layer
var activityLayer = new ol.layer.Vector({
source: new ol.source.Vector()
});
// 创建一个活动图标需要的Feature,并设置位置
var activity = new ol.Feature({
geometry: new ol.geom.Point([center[0]- 550*1000/2 + 390 * 1000, center[1]-344*1000/2 + (344 - 145) * 1000])
})
// 设置Feature的样式,使用小旗子图标
activity.setStyle(new ol.style.Style({
image: new ol.style.Icon({
src: '../img/flag_right.png',
anchor: [0, 1],
scale: 0.2
})
}));
// 添加活动Feature到layer上,并把layer添加到地图中
activityLayer.getSource().addFeature(activity);
map2.addLayer(activityLayer);
</script>
注释足够帮助大家理解代码意图,我想最关键的在于activity
这个feature
的位置为什么要这样计算: [center[0]- 550*1000/2 + 390 * 1000, center[1]-344*1000/2 + (344 - 145) * 1000]
。 如果翻译成下面这样,你可能会更容易理解:extentLeft+picX, extentTop+picY
,此处的picX
和picY
显然是需要在图片像素位置的基础上放大1000倍,才能对应于地理位置。 [center[0]- 550*1000/2
对应的就是extentLeft
, center[1]-344*1000/2
对应的是extentBottom
,并不是extentTop
,所以我们要做一个简单的计算(344 - 145) * 1000
,而不是直接用145*1000
。
从图片的像素坐标转换为地图的地理坐标,关键在于通过像素大小,映射到一个地理的extent
,希望能理解这个过程。 在此基础上,就能充分应用OpenLayers 3的功能了。
对于图片比较大的情况,可以自行切片,然后分片加载,从而拼成一整张地图,可按照上面的方法自行尝试,作为课后练习。