OL加载地图数据

12/24/2022

WebGIS里最基础的工作就是将所需求的地图数据加载和显示,再结合相关业务的操作。在WebGIS开发中,通常是调用地图服务器上发布的地图服务来加载数据,如 ArcGIS Server发布的动态地图服务、瓦片地图服务和要素地图服务等或是GeoServer发布的WMSWMTSWFS服务等。除了地图服务的形式外,还有加载地图矢量要素文件的形式,如GeoJSONshapefileKML等,甚至还有各种公共网络的地图服务,例如百度地图、天地图等。

# 矢量数据

矢量数据属于客户端图层,确切的说是在客户端渲染的矢量图层。

数据通过Source(数据源)和Format(解析器)或者Feature(要素类)的方式加载,再用ol.Feature要素类进行组织,设置Feature中的style属性配置矢量图层的样式,最后通过Layer渲染显示。

矢量数据所涉及的类主要是ol.source.Vector类加载,数据源的加载方式有如下两者:

  1. url+format方式:通过设置矢量数据url和相应数据格式的解析器加载数据

    //方式一
    /**
     * new VectorLayer({options})
     *主要属性:
     * source:指定数据源
     * opacity:不透明度,[0,1]0是完全透明,1是不透明
     * visible:可见性,
     * extent:渲染边界,边界外的将不被渲染
     * zIndex:在渲染图层时,会先按zIndex的值进行排序。如果未定义,在添加到map的图层集合时,ol会自动分配一个zIndex
     * map:设置该图层为叠加层,不在map的图层集合中管理,将被放置在top的位置(掉setMap()方法)
     */
    import VectorSource from 'ol/source/Vector';
    
    //加载 GeoJSON 矢量数据Vector服务图层
    import GeoJSON from 'ol/format/GeoJSON'
    let geoJsonLayer = new VectorLayer({
        source : new VectorSource({
            url: 'data/640106_3857.geojson',
            format: new GeoJSON()
        }),
        name: '宁夏-3857',
        id: 'GeoJSON-NX-3857'
    })
    
    //加载KML矢量数据Vector服务图层
    import KML from 'ol/format/KML'
    let kmlLayer = new VectorLayer({
        source:new VectorSource({
            url: 'data/kml/2012_Earthquakes_Mag5.kml',
            format: new KML({
                extractStyles:false
            })
        }),
        name:"点(KML格式的矢量图层)",
        id:"kmlData"
    }),
     
    //加载gpx矢量数据Vector服务图层
    import GPX from 'ol/format/GPX'
    
    let gpxLayer = new VectorLayer({
        source:new VectorSource({
            url:'data/gpx/fells_loop.gpx',
            format:new GPX()
        }),
        name:"GPX数据",
        id:"gpxData"
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
  2. 在loader函数中添加 feature 的方式:设置features参数静态的加载矢量数据或调用addFeature()addFeatures()进行动态加载。

    import './style.css';
    import {Map, View} from 'ol';
    import TileLayer from 'ol/layer/Tile';
    import OSM from 'ol/source/OSM';
    import GeoJSON from 'ol/format/GeoJSON'
    import VectorSource from 'ol/source/Vector';
    import VectorLayer from 'ol/layer/Vector';
    import { fromLonLat } from 'ol/proj';
    import { bbox } from 'ol/loadingstrategy'
    let vectorSource = new VectorSource({
        format: new GeoJSON(),
        loader: (extent, resolution, projection ) => {
            let proj = projection.getCode();
            let url = 'http://gisserver.tianditu.gov.cn/TDTService/wfs?service=WFS&' +
            'version=1.1.0&request=GetFeature&typename=LRRL&' +
            'outputFormat=application/json&srsname=' + proj + '&' +
            'bbox=' + extent.join(',') + ',' + proj;
            let xhr = new XMLHttpRequest();
            xhr.open('GET', url);
            let onError = () => {
                vectorSource.removeLoadedExtent(extent);
            }
            xhr.onerror = onError;
            xhr.onload = () => {
                if (xhr.status == 200) {
                    vectorSource.addFeatures(
                        vectorSource.getFormat().readFeatures(xhr.responseText));
                } else {
                    onError();
                }
            }
            xhr.send();
        },
        strategy: bbox
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35

以上两种方式是从已有的数据文件或服务中加载的,当用户客户端绘制几何图形的时候,我们也是将这些几何图形用ol.Feature组织,放到数据源ol.source.Vector中用于创建矢量图层,显示数据。

import './style.css';
import {Feature, Map, View} from 'ol';
import { Point } from 'ol/geom';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import OSM from 'ol/source/OSM';
import VectorSource from 'ol/source/Vector';
/**
 * Feature直接加载
 */
let pointFeature =  new Feature({
    geometry: new Point([12703928.421,2575539.521]),
    name : '一个点'
})
let pointLayer = new VectorLayer({
    source: new VectorSource({
        features: [pointFeature],
        id: 'pointLayer'
    })
})

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    }),
    pointLayer
  ],
  view: new View({
    center: [12703928.421,2575539.521],
    zoom: 8
  })
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 栅格数据

栅格数据主要是在地图服务器上根据请求的范围和尺度渲染生成的单张图片(包括影像)或是根据请求的瓦片级别和行列号,响应回来的按照特定切图策略裁剪形成的缓存图片集即瓦片地图。

由于地图数据的供应商或GIS平台不同,会有不同的数据格式。在Web端通常以数据服务的形式提供数据,有的是标准的OGC服务,也有的是平台自定义的数据服务。

ol帮我们封装了一些平台常用的瓦片地图服务的数据源,如ArcGISol.source.TileArcGISRest、开源地图OpenStreetMapol.source.SOM,微软必应Bingol.source.BingMaps。对于常规的在线瓦片地图服务通过ol.source.XYZ类来加载。

import '../style.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import TileArcGISRest from 'ol/source/TileArcGISRest';
import XYZ from 'ol/source/XYZ';
import BingMaps from 'ol/source/BingMaps';

let url = 'https://sampleserver6.arcgisonline.com/ArcGIS/rest/services/USA/MapServer';
let onlineTileUrl =  'http://server.arcgisonline.com/arcgis/rest/services/USA_Topo_Maps/MapServer/tile/{z}/{y}/{x}'
let bingKey = 'AmosL5A0GtVryl4sXNZm6U5EQMD6brAd5E8AJPGJf8AUU1saDYXDkb5CwQFijans';


const map = new Map({
  target: 'map',
  layers: [
    //加载OSM瓦片图层
    new TileLayer({
      source: new OSM()
    }),
    //加载ArcGIS MapServer瓦片服务图层
    /**
     * ol.layer.Tile
     * 主要属性:
     * source:指定数据源
     * opacity:不透明度,[0,1]0是完全透明,1是不透明
     * visible:可见性,
     * z-index: 地图层级
     * proload:预加载低层级的瓦片数据,默认值为0,表示不预加载
     * map:设置该图层为叠加层,不在map的图层集合中管理,将被放置在top的位置(掉setMap()方法)
     */
    new TileLayer({
      source: new TileArcGISRest({
        url
      })
    }),
    /**
     * 加载ArcGIS online地图
     * extent:渲染边界,边界外的将不被渲染
     */
    new TileLayer({
      source: new XYZ({
        url:onlineTileUrl
      })
    }),
    /**
     * 加载Bing底图
     */
    new TileLayer({
      source: new BingMaps({key:bingKey,imagerySet:"AerialWithLabelsOnDemand"})
    })
  ],
  view: new View({
    center: [0, 0],
    zoom: 2
  })
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

当需要加载单张图片的数据时,面对不同的服务类型使用相应的数据源和渲染器。例如WMS服务使用ol,source.ImageWMSol.layer.Image,加载调用GetMap接口返回的单张图片。

new ol.layer.Image({
    source:new ol.source.ImageWMS({
		url:'http://localhost:8081/geoserver/shenzhen/wms',
		params: {
			//WIDTH, HEIGHT, BBOX and CRS (SRS for WMS version < 1.3.0) 将被动态设置.
			'LAYERS': 'shenzhen:ShenzhenLSWI_2016_S2L1C',
			'VERSION':'1.1.1'//默认1.3.0
		},
		//远程WMS服务器的类型
		serverType: 'geoserver',
	})
})
1
2
3
4
5
6
7
8
9
10
11
12

# 公共地图数据

国内互联网上有像天地图、百度、高德等地图厂商,国外也有微软的Bing、Mapbox、Google等公司提供地图服务,这些服务都可以根据其提供的Web API接口进行调用。

  • 百度地图

    import './style.css';
    import {Map, View} from 'ol';
    import TileImage from 'ol/source/TileImage';
    import * as olProj from 'ol/proj';
    import TileGrid from 'ol/tilegrid/TileGrid';
    import TileLayer from 'ol/layer/Tile';
    var resolutions = [];
    for(var i=0;i<19;i++){
        resolutions[i] = Math.pow(2,18 - i)
    }
    
    const map = new Map({
        target:'map',
        layers:[
            new TileLayer({
                id:'BMap',
                source: new TileImage({
                    //设置坐标参考
                    projection: olProj.get('EPSG:3857'),
                    //设置分辨率
                    tileGrid: new TileGrid({
                        origin:[0,0],
                        resolutions:resolutions
                    }),
                    //设置百度地图的瓦片地图请求地址
                    tileUrlFunction : (tileCoord,pixelRatio,proj) => {
                        if(!tileCoord){
                            return "";
                        }
                        var z = tileCoord[0];
                        var x = tileCoord[1];
                        var y = tileCoord[2];
    
                        if(x < 0){
                            x = "M" + (-x);
                        }
                        if(y < 0){
                            x = "M" + (-y);
                        }
                        return "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x=" + x + "&y=" + y + "&z=" + z + "&style=pl&udt=20151021&scale=1&p=1";
                    }
                })
            }),
        ],
        view: new View({
            center: [12698769.380277092, 2579510.250552084],
            zoom: 11
        })
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
  • 天地图

    import './style.css';
    import {Map, View} from 'ol';
    import XYZ from 'ol/source/XYZ';
    import TileLayer from 'ol/layer/Tile';
    
    var key = "bf156eb3c72350d62b008dc8a4ae1016";
    
    const map = new Map({
        target:"map",
        layers:[
            new TileLayer({
                id:"tdt_vec",
                title:"天地图矢量图层",
                source: new XYZ({
                    url: 'http://t' + Math.round(Math.random() * 7) + '.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk='+key,
                    crossOrigin:"anonymous",
                    wrapX:false
                })
            }),
            new TileLayer({
                id:"tdt_cva",
                title:"天地图矢量注记图层",
                source: new XYZ({
                    url:"https://t2.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk="+key,
                    crossOrigin:"anonymous",
                    wrapX:false
                })
            })
        ],
        view: new View({
            center: [12698769.380277092, 2579510.250552084],
            zoom: 11
        })
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
  • MapBox

    import './style.css';
    import {Map, View} from 'ol';
    import XYZ from 'ol/source/XYZ';
    import MVT from 'ol/format/MVT';
    import TileLayer from 'ol/layer/Tile';
    import VectorTileLayer from 'ol/layer/VectorTile';
    import VectorTile from 'ol/source/vectortile';
    
    var key = "pk.eyJ1IjoicWl1c2hpamllIiwiYSI6ImNrYTYzNmlhdDAzb2YydG13YjZic2t2M3AifQ.XiCKl8HOEAy0MBo5v2yjvA";
    
    const map = new Map({
        target:"map",
        layers:[
            new TileLayer({
                id:"mapbox_v1",
                source: new XYZ({
                    url: 'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}?access_token='+key
                })
            }),
            new VectorTileLayer({
                declutter: true,
                source: new VectorTile({
                    url:"http://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.mvt?access_token="+key,
                    format:new MVT(),
                    style:"mapbox://styles/mapbox/streets-v11"
                })
            })
        ],
        view: new View({
            center: [12698769.380277092, 2579510.250552084],
            zoom: 11
        })
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
Last Updated: 10/6/2023, 6:06:42 PM