前言:本篇文章面向于刚接触openlayers,看过/写过一点,懂了,但没完全懂的看客。

一、openlayers是什么,有什么相似的库

官网OpenLayers - Welcome

        openlayers是一个显示地图和地理空间数据并与之交互的库。简单的讲就是画出地图,并在地图上绘制图形、文案,或计算相关数据等。

        相似的库: 百度地图、高德地图、cesium;其中openlayers、百度、高德是2D地图;cesium是3D

二、几个基础变量的理解

首先用一个例子来引入,假如现在我要实现在地图上标点。代码大致如下:

// <div id="map" style="width: 100%, height: 400px"></div>
import 'ol/ol.css';
import { Map, View, Feature, Overlay } from 'ol';
import { Circle as CircleStyle, Fill, Stroke, Style, Icon, Text } from 'ol/style';
import { LineString, Polygon, Point } from 'ol/geom';
import * as sources from 'ol/source.js';
import { OSM, XYZ, TileArcGISRest, Vector as VectorSource, WMTS } from 'ol/source';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';

let pointPos = [121, 29] //经纬度坐标
let map = new Map({
    target: 'map',
    layers: new TileLayer({
		source: new sources.BingMaps({
			key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', //自己获取的token
			culture: 'zh-cn'
		})
	})
}); //新建一个地图map,地图上的所有东西都放在map里面

let point = new Feature({
	geometry: new Point(pointPos)
});//构造点
let pointLayer = new VectorLayer({
	source: new VectorSource({//设置图层
		features: [point]
	}),
	style: new Style({//设置features的样式
		image: new CircleStyle({//具体设置点的样式
			radius: 4,
			fill: new Fill({
				color: 'black'
			})
		})
	})
});
map.addLayer(pointLayer); //将图层添加到地图上

        可以看到,简单的标个点还要经历很多步骤。首先,取一个dom对象新建map,设置瓦片图层(用于显示基本地图);其次,设置一个矢量图层(用于绘制图形);接着,在矢量图层上新建Feature(要绘制的图形)并设置样式;最后,把矢量图层添加到map上。

接下来,我会用自己的理解,一一解释这些关键词的意义和作用(具体变量、键值、字段参考官方文档OpenLayers v6.9.0 API - Index

1、map

        以id为关键字段取一个dom元素作为map的容器,注意给宽高。

2、TileLayer(瓦片图层)

        地图可以有许多图层。但是一般都至少有一个基本的瓦片图层,用于显示基本地图。你可以选择不同类别的瓦片图层来满足不同需求。

3、VectorLayer(矢量图层)

        该图层可以自由添加,一般用于显示绘制的图形,可以设置各种图形后通过addLayer添加,removeLayer删除。并且后续只要操作该图层就可以修改样式,不会影响到其它图层。

4、Feature

        为矢量图层中的一个属性,用于展示某个图层中的某个图形,该属性可以单独setStyle。并且可以单独操作某个图层的Feature【通过drawLayer.getSource().addFeature(feature)添加,其中,drawLayer为图层名;feature为该属性名】。

        feature的其中一个作用:有这样一个场景,现在有多个矢量图层,图层1画点线面、图层2画不规则图形、图层3显示正射影像。所以通过Feature属性分别对不同图层进行操作,而不是每次都addLayer,造成图层混乱。

三、根据经纬度绘制点线面

OpenLayers中如何通过坐标绘制点线面 - SuperMap技术问答社区

通过基本步骤一步步将已经拿到的经纬度添加到地图中,详情参考上述网址

// 构造点
var pointsList = [
	[2823.940, -4690.000],
	[3448.940, -4690.301],
	[3816.561, -3810.125],
	[3917.383, -3609.158],
	[3976.983, -3490.291],
	[4020.004, -4377.027],
	[4076.265, -4382.939],
	[4215.049, -4382.333],
	[4428.156, -4382.285]
];
// 在所有离散gps信号点添加到地图上
for (i = 0; i < pointsList.length; i++) {
	var point = new ol.Feature({
		geometry: new ol.geom.Point(pointsList[i])
	});//构点
	var pointLayer = new ol.layer.Vector({
		source: new ol.source.Vector({
			features: [point]
		}),
		style: new ol.style.Style({
			image: new ol.style.Circle({
				radius: 4,
				fill: new ol.style.Fill({
					color: 'black'
				})
			})
		})
	});
	map.addLayer(pointLayer);
}

// 构造线
// 将由离散gps信号点生成的线路添加到地图上
var roadLine = new ol.geom.LineString(pointsList);
var roadLineSource = new ol.source.Vector({
	features: [new ol.Feature(roadLine)]
});
var roadLineLayer = new ol.layer.Vector({
	source: roadLineSource,
	style: new ol.style.Style({
		stroke: new ol.style.Stroke({
			color: 'red',
			width: 3
		})
	})
});
map.addLayer(roadLineLayer);

// 构造面
var polygon = new ol.geom.Polygon([[[0, 0], [-10, 30], [-30, 0], [0, 0]]]);
var polygonSource = new ol.source.Vector({
	features: [new ol.Feature(polygon)],
	wrapX: false
});
vectorLayer = new ol.layer.Vector({
	source: polygonSource,
	style: new ol.style.Style({
		stroke: new ol.style.Stroke({
			color: 'red',
			width: 3
		}),
		fill: new ol.style.Fill({
			color: 'rgba(0, 0, 255, 0.1)'
		})
	})
});
map.addLayer(vectorLayer);

四、手动在地图上绘制点线面

简单版Draw and Modify Features

可加细节Measure

五、测量与计算

        openlayers有自带,但是我用了turf插件(Turf.js中文网),这个插件在图形测量与计算方面会更强大一些。

        使用起来非常简单,除了简单的长度,区域面积外,还能满足其他奇奇怪怪的需求。(PS:我遇到个需求,计算折线的中点,愣是没想明白怎么搞,用这个插件,2分钟搞定)

六、图层切换

        2个图层的切换刚开始我用add和remove,但是图层一旦多了起来,这样的操作显然不具备可行性。后面我控制图层的显隐来实现图层切换。核心代码如下:

map = new Map({
	target: 'map',
	layers: [BingMaps, drawLayer, rasterProject, designLayer], //这里有4个图层(包括瓦片图层BingMaps)
	view: viewer,
	controls: defaultControls({
		zoom: false
	})
});
      
      
if(xxxx) { //达到某个条件后,给rasterProject设置图层和显隐
	let source = new XYZ({ //图层是XYZ类,可以自己选择其他图层
		url: `xxxxxxxxxx` //自己的url
	});
	rasterProject.setSource(source);
	rasterProject.setVisible(true);
}

欢迎指正错误