利用Openlayers4实现地图遮罩效果(二)

效果对比

在之前实现的遮罩效果《利用Openlayers4简单实现地图遮罩效果(一)》,在深色背景的底图上,对要突出的区域采用半透明遮罩,以此来突出该区域。暂且称之为中心遮罩,遮罩前后对比如下图:
利用Openlayers4实现地图遮罩效果(二)_第1张图片
利用Openlayers4实现地图遮罩效果(二)_第2张图片
但是有时底图颜色偏白,这时候不再适合对要突出的区域采用遮罩,而是要对突出区域之外进行遮罩处理。暂且称为四周遮罩如下图:利用Openlayers4实现地图遮罩效果(二)_第3张图片
利用Openlayers4实现地图遮罩效果(二)_第4张图片

代码实现

实现代码如下:
js代码

(function(){
    
    var map, converLayer;
    function initMap() {
        var baselayer = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetGray/MapServer/tile/{z}/{y}/{x}'
            })
        });
    
        map = new ol.Map({
            target: 'map',
            layers: [baselayer],
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [112, 36],
                zoom: 6
            })
        });

        var mystyle = new ol.style.Style({
            fill: new ol.style.Fill({
                color:"rgba(72,61,139, 0.4)",
            }),
            stroke: new ol.style.Stroke({
                color:"#BDBDBD",
                width:2
            })
        });
        converLayer = new ol.layer.Vector({
            source: new ol.source.Vector(),
            style: mystyle
        });
        map.addLayer(converLayer);
    }

    //todo
    //添加遮罩
    function addconver(data) {
        $.getJSON(data, function(data) {
            var fts = new ol.format.GeoJSON().readFeatures(data);
            var ft = fts[0];
            var converGeom = erase(ft.getGeometry());

            var convertFt = new ol.Feature({
                geometry: converGeom
            })
            converLayer.getSource().addFeature(convertFt);
        })
    }

    // 擦除操作,生成遮罩范围
    function erase(geom) {
	  var extent = [-180,-90,180,90];
	  var polygonRing = ol.geom.Polygon.fromExtent(extent);
	  if (!geom instanceof ol.geom.Polygon) {
	    console.log('geom的类型必须是Polygon')
	    return
	  } 
	  var coords = geom.getCoordinates();
	  coords.forEach(coord =>{ 
	      var linearRing = new ol.geom.LinearRing(coord[0]);
	      polygonRing.appendLinearRing(linearRing);
	  })
	  return polygonRing;
	}
    

    initMap();
    var dataURL = '/static/data/shanxi.geojson'
    addconver(dataURL);
})();

html代码

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>周边遮罩title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css">
    <script src="/static/js/node_modules/jquery/dist/jquery.min.js">script>
    <script src="https://openlayers.org/en/v4.6.5/build/ol.js">script>
    <style>
        head,body,#map{
            width: 100%;
            height: 100%;
            background-color: black;
        }
    style>
head>
<body>
    <div id="map">div>
    <script src="/static/js/conver.js">script>
body>
html>

原理

利用GIS空间运算中的擦除操作,熟悉GIS数据处理的同学应该不陌生这个操作。在Openlayers中,虽然并不支持空间运算,但是我们可以取构建擦除运算的结果。正常情况下,擦除运算的结果类似一个空心环,分为外环和内环,内外环之间为填充区域。

环装几何

openlayers支持环状几何,我们将地图周边视为外环,将中心视为内环,构建环,在利用半透明填充即可实现四周遮罩。具体方法见js代码中的erase函数

后记

这篇文章,由于写的时候只是为了展示遮罩,一些地方不够严谨或者未说明,导致很多同学在参考运用的时候,出现了一些差错,没有达到预计想要的遮罩,然后私信或者留言给我进行咨询。这里根据他们反馈的情况和问题,以及排除思路,总结说明以下,以供后续大家参考。

1. 看不到遮罩效果

这个问题比较大,可能的原因也比较多,可以从以下几点进行排查

  1. erase函数的参数geom不是Polygon类型。
    这个会导致linearRing构造失败,导致内环没添加到polygonRing。linearRing的构造方法,参数是一个Array{ol.coordinate},不能是其他的结构。
    如果你的geom不是Polygon类型也没关系,改造erase函数内的代码,使给linearRing构造方法的参数传正确即可。
  2. 坐标系问题
    上面代码中,map对象和测试数据,均采用的是EPSG:4326坐标系(即WGS84)。可以采取其他的坐标系,但是最起码要保证你的map对象的坐标系、图层的坐标系、数据坐标系是一致的。如果不一致,自然没法正常展示。
  3. 地图中心点不对
    可以采用map.getView().fit()方法,传入遮罩的geometry,使地图缩放到遮罩的位置。

你可能感兴趣的:(Openlayers4笔记,openlayers开发,遮罩,openlayers,覆盖层,地图,webgis)