本博客合集是我的openlayers学习笔记,希望能帮助到刚开始接触openlayers的同学
@commnet 所用openlayers版本:v5.3.0
@commnet 阅读本文前需要对前端知识有一定的了解
@comment 本文内容只提供参考,建议结合openlayers官网的API和examples来学习
@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);