高级视图定位#openlayers入门笔记#

1,097 阅读4分钟

本博客合集是我的openlayers学习笔记,希望能帮助到刚开始接触openlayers的同学

@commnet 所用openlayers版本:v5.3.0

@commnet 阅读本文前需要对前端知识有一定的了解

@comment 本文内容只提供参考,建议结合openlayers官网的APIexamples来学习

@comment 部分代码参考了@老胡

有些情景需要在地图上对图形进行定位,如点击了某文本中的“泰坦尼克号”链接,希望自动在地图上定位出该船的位置。

在确定了地图视角和位置的情况下,图形也就定位了,常有以下几种方式的定位(请忽略我这吃力的网速):

  • 地图内容区外接图形(内容区外接多边形的上下顶点)

  • 地图内容区以最大的整数zoom,定位完整图形(当前zoom是能看到完整多边形最大的整数zoom了)

  • 地图内容区以最小的整数zoom,让图形铺满地图

  • 地图内容区以某分辨率,中心定位图形(中间的小圆圈)

  • 地图内容区相对于地图视窗大小,以指定偏移量定位图形(小圆圈偏移到了指定的正方形区域中)

注:这里的“内容区”是我的理解,可以把地图的view理解成css中的盒模型,当view.fit函数(下面会提到)没有指定padding参数时,内容区就是整个view,一旦指定了padding参数,内容区就变成了padding圈起来的视区了。

  • 创建5个功能测试按钮和地图容器
<button id="zoomtoswitzerlandbest">外接匹配</button><br />
<button id="zoomtoswitzerlandconstrained">最佳分辨率匹配</button><br />
<button id="zoomtoswitzerlandnearest">最佳范围匹配</button><br />
<button id="zoomtolausanne">点居中</button><br />
<button id="centerlausanne">定位点到指定位置</button>
<div class="mapcontainer">
	<div id="map" class="map"></div>
	<div class="padding-top"></div>
	<div class="padding-left"></div>
	<div class="padding-right"></div>
	<div class="padding-bottom"></div>
	<div class="center"></div>
</div>
  • 添加样式
.mapcontainer {
	position: relative;
	margin-bottom: 20px;
}

.map {
	width: 1000px;
	height: 600px;
}

div.ol-zoom {
	top: 178px;
	left: 158px;
}

div.ol-rotate {
	top: 178px;
	right: 58px;
}

.map div.ol-attribution {
	bottom: 30px;
	right: 50px;
}

.padding-top {
	position: absolute;
	top: 0;
	left: 0px;
	width: 1000px;
	height: 170px;
	background: rgba(255, 255, 255, 0.5);
}

.padding-left {
	position: absolute;
	top: 170px;
	left: 0;
	width: 150px;
	height: 400px;
	background: rgba(255, 255, 255, 0.5);
}

.padding-right {
	position: absolute;
	top: 170px;
	left: 950px;
	width: 50px;
	height: 400px;
	background: rgba(255, 255, 255, 0.5);
}

.padding-bottom {
	position: absolute;
	top: 570px;
	left: 0px;
	width: 1000px;
	height: 30px;
	background: rgba(255, 255, 255, 0.5);
}

.center {
	position: absolute;
	border: solid 1px black;
	top: 490px;
	left: 560px;
	width: 20px;
	height: 20px;
}
  • 创建地图对象
//在矢量图层上添加一个多边形(ol.geom.Polygon)和一个点(ol.geom.Point)
var source = new ol.source.Vector({
	url: '../data/switzerland.geojson',
	format: new ol.format.GeoJSON()
});

//创建样式对象
var style = new ol.style.Style({
	fill: new ol.style.Fill({
		color: 'rgba(255, 255, 255, 0.6)'
	}),
	stroke: new ol.style.Stroke({
		color: '#319FD3',
		width: 1
	}),
	image: new ol.style.Circle({
		radius: 5,
		fill: new ol.style.Fill({
			color: 'rgba(255, 255, 255, 0.6)'
		}),
		stroke: new ol.style.Stroke({
			color: '#319FD3',
			width: 1
		})
	})
});

//创建矢量图层
var vectorLayer = new ol.layer.Vector({
	source: source,
	style: style
});

var view = new ol.View({
	center: [0, 0],
	zoom: 1
});

//地图包含底图和矢量图层
var map = new ol.Map({
	layers: [
		new ol.layer.Tile({
			source: new ol.source.OSM()
		}),
		vectorLayer
	],
	target: 'map',
	view: view
});
  • 为5个功能测试按钮添加点击事件,注释中详细说明了几种定位的用法和区别
//多边形的外接匹配:地图的内容区外接多边形
var zoomtoswitzerlandbest = document.getElementById('zoomtoswitzerlandbest');
zoomtoswitzerlandbest.addEventListener('click', function() {
	var feature = source.getFeatures()[0];
	var polygon = feature.getGeometry();
	//将view理解成css中的盒模型,多边形相对于padding里的内容区进行定位
	//constrainResolution默认为true,这里设为false即不限制分辨率,zoom不必是整数,因此可以实现精确的外接定位
	view.fit(polygon, {
		padding: [170, 50, 30, 150],
		constrainResolution: false
	});
	console.log(map.getView().getZoom())
}, false);

//多边形的最佳分辨率匹配:再继续放大,多边形就超出内容区了
var zoomtoswitzerlandconstrained =
	document.getElementById('zoomtoswitzerlandconstrained');
zoomtoswitzerlandconstrained.addEventListener('click', function() {
	var feature = source.getFeatures()[0];
	var polygon = feature.getGeometry();
	//如果不写constrainResolution,默认为true
	//即该定位结果是在zoom为整数的前提下,能看到完整多边形的最大分辨率
	view.fit(polygon, {
		padding: [170, 50, 30, 150]
	});
	console.log(map.getView().getZoom())
}, false);

//多边形的最佳范围匹配
var zoomtoswitzerlandnearest =
	document.getElementById('zoomtoswitzerlandnearest');
zoomtoswitzerlandnearest.addEventListener('click', function() {
	var feature = source.getFeatures()[0];
	var polygon = feature.getGeometry();
	//设置nearest为true,以最小的整数zoom,让图形铺满地图
	view.fit(polygon, {
		padding: [170, 50, 30, 150],
		nearest: true
	});
	console.log(map.getView().getZoom())
}, false);

//将点以某分辨率居中
var zoomtolausanne = document.getElementById('zoomtolausanne');
zoomtolausanne.addEventListener('click', function() {
	var feature = source.getFeatures()[1];
	var point = feature.getGeometry();
	//将点point以分辨率minResolution居中
	view.fit(point, {
		padding: [170, 50, 30, 150],
		minResolution: 250
	});

}, false);

//将点相对map.getSize()以指定偏移量定位
var centerlausanne = document.getElementById('centerlausanne');
centerlausanne.addEventListener('click', function() {
	var feature = source.getFeatures()[1];
	var point = feature.getGeometry();
	var size = map.getSize();
	console.log(size)
	//相对于size,点point距离顶部偏移了500px,距离左边偏移了570px
	view.centerOn(point.getCoordinates(), size, [570, 500]);
}, false);