OpenLayer基础(二)——图层(layer)
在openlayers中,Layer是Map的必须组成,也是核心要素,今天学习利用openlayers加载各种不同类型的地图数据。内容包括:
- 利用openlayers加载瓦片数据;
- 利用openlayers加载图片数据
- 利用openlayers加载矢量数据
- 利用openlayers加载矢量瓦片数据
1.Layer
ol定义了四种基本的图层类型,分别是Tile、Image、Vector、VectorTile,这四种类有一个共同的基类Layer,它们的大多数属性和方法都继承自这个类。下面是ol对Layer类的定义:
Abstract base class; normally only used for creating subclasses and not
instantiated in apps.A visual representation of raster or vector map data.
Layers group together those properties that pertain to how the data is to be
displayed, irrespective of the source of that data.
Layer的主要属性:
- opacity,不透明度,默认为 1 ,即完全不透明;
- zIndex,图层的叠放次序,默认为0,值最小的图层位于最下方;
- visible,是否可见,默认为 true ;
- extent,图层渲染的区域,格式为[minx,miny,maxx,maxy]。如果没有设置该参数,图层就不会显示;
- minResolution,最小分辨率,当图层的缩放级别小于这个分辨率时,图层就会隐藏;
- maxResolution,最大分辨率,当图层的缩放级别等于或超过这个分辨率时,图层就会隐藏;
- source,图层的来源。
Layer的主要方法:
- getLayersArray(),得到所有图层;
- getLayerStatesArray(),得到所有图层状态;
- getSource(),得到相应图层的来源;
- getSourceState(),得到相应图层的来源状态;
- setSource(),设置图层 source 属性,参数为一个 source 对象;
- setMap(),添加Layer到Map,并由Map管理。
2. Tile/TileLayer
Tile指瓦片数据,是WebGIS最常用的数据类型,TileLayer在继承Tile所有属性和方法的同时自己定义了preload
属性以及对应的getPreload()
、setPreload()
方法,preload指低分辨率瓦片预加载的等级,默认为0,即不预加载。显示任何一幅地图需要3个要素:
- 容器,即地图显示在什么地方;
- 数据源,即显示哪个数据;
- 视图,即地图的坐标、范围和等级。
所以,利用ol显示瓦片数据的过程是:
- 创建容器并定义地图,和leaflet一样,地图必须显示在一个div中,因此首先创建一个div:
<div id="map" class="map"></div>
- 定义数据源,即创建TileLayer(当然ol中图层和数据源是两个不同的类,这里就放在一起了):
var layer=new ol.layer.Tile({
source: new ol.source.OSM(),
visible:true,
opacity:0.8,
zIndex: 1
})
- 定义视图,视图和数据源息息相关,不可分离:
var view=new ol.View({
center:ol.projfromLonLat([37.41, 8.82]),
zoom:4
})
-创建地图
var map = new ol.Map({
target: 'map',
layers: [
layer
],
view: view
});
到此,已经完成了显示一个瓦片数据的全部过程。关于以上代码:
- 和leaflet一样,地图必须显示在一个div中。
target:'map'
指定了地图要显示在id为map的div中new ol.layer.Tile({ source: new ol.source.OSM() })
定义了一个图层,数据来源是OpenStreetMap提供的切片数据。new ol.View({ center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 })
定义了地图的中心位置,范围和层级。ol.proj.fromLonLat([37.41, 8.82])
是将一个经纬度坐标转换成投影坐标。
fromLonLat(coordinate, opt_projection)
coordinate:经纬度坐标
projection:目标投影,默认Web Mercator, 即 'EPSG:3857'
3. Image/ImageLayer
Image指图片数据,ol可以将网络或本地的图片加载到网页中,ImageLayer并没有增加任何属性和方法,加载一个图片数据,需要两个必要参数:一是extent,另一个是projection。现在我有一个生态系统分布的图片,首先,利用ArcGIS打开地图数据,获得其范围和坐标系。
根据上图定义extent和projection:
var extent=[-1834184.237800,2231702.381200,-672568.125000,2845554.176000]
var proj=new ol.proj.Projection({
code:'EPSG:102025',
extent:extent
})
然后将图片加载到网页中:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Image(
{
source:new ol.source.ImageStatic({
url:'../img/2015.jpg',
projection:proj,
imageExtent: extent
})
}
)
],
view: new ol.View({
center: ol.extent.getCenter(extent),
//center:ol.proj.fromLonLat([98,34],proj),
projection:proj,
zoom: 1
})
});
4.Vector/VectorLayer
Vector指矢量数据,VectorLayer自己定义了很多属性和方法:
- renderOrder:渲染地理要素时的顺序,一般情况下,在渲染之前,要素是基于一定规则排序的,而渲染就是根据这个顺序进行依次渲染的,这个参数便指定了这个排序规则,如果赋值为 null ,那么就不会对地理要素进行排序,渲染也不会有一定的顺序;
- renderBuffer:默认值为100;
- style:规定了矢量图层的样式,即配色、形状等;
- renderMode:渲染模式,Image表示数据被渲染为图像,点和文本信息会随图像旋转,缩放时像素也会被缩放;Vector表示将数据渲染为向量,最精确但性能较慢。
- updateWhileAnimating:当有动画特效时,地理要素是否被重新创建,默认是 false;
- updateWhileInteracting:当地理要素交互时,是否重新渲染。
openlayers加载矢量数据需要转换成GeoJSON格式,以shp数据为例,先将数据转换成GeoJSON格式,转换方法很多,推荐两种:一是利用QGIS另存为功能,二是利用python geopandas的to_josn()
方法,批量转换时推荐。ol加载GeoJSON的和前两种大同小异:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Vector(
{
source: new ol.source.Vector({
projcetion: 'EPSG:4326',
url: '../data/glass.geojson',
format: new ol.format.GeoJSON()
})
}
)
],
view: new ol.View({
center: [11046067.83154739,4094171.054588544],
zoom: 6,
projcetion: "EPSG:4326"
})
});
如果要自己定义图层样式:
var fill = new ol.style.Fill({
color: 'rgba(255,123,100,0.8)'
});
var stroke = new ol.style.Stroke({
color: '#3399CC',
width: 1.25
});
var styles =
new ol.style.Style({
image: new ol.style.Circle({
fill: fill,
stroke: stroke,
radius: 4
}),
fill: fill,
stroke: stroke
})
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Vector(
{
source: new ol.source.Vector({
projcetion: 'EPSG:4326',
url: '../data/glass.geojson',
format: new ol.format.GeoJSON()
}),
style:styles
}
)
],
view: new ol.View({
center: [11046067.83154739,4094171.054588544],
zoom: 6,
projcetion: "EPSG:4326"
})
});
展示一下效果:
5. Vector/VectorLayer
已经快凌晨了,累的不行了,直接上代码
var key = 'Your Mapbox access token from http://mapbox.com/ here';
var map = new ol.Map({
layers: [
new ol.layer.VectorTile({
declutter: true,
source: new ol.source.VectorTile({
attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
'© <a href="https://www.openstreetmap.org/copyright">' +
'OpenStreetMap contributors</a>',
format: new ol.format.MVT(),
url: 'https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
'{z}/{x}/{y}.vector.pbf?access_token=' + key
}),
style: createMapboxStreetsV6Style(ol.style.Style, ol.source.Fill, ol.style.Stroke, ol.style.Icon, ol.style.Text)
})
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
})
后记:现在是凌晨5点整,Firefox浏览器坑我,好几次崩溃让我前功尽弃,以后要考虑换浏览器了。学习了openlayer第一个感觉就是比leaflet要难很多,也要强大很多,后面有时间会继续更新,晚安。