7-高级视图定位

本博客合集是我的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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。