效果对比
在之前实现的遮罩效果《利用Openlayers4简单实现地图遮罩效果(一)》,在深色背景的底图上,对要突出的区域采用半透明遮罩,以此来突出该区域。暂且称之为中心遮罩,遮罩前后对比如下图:
但是有时底图颜色偏白,这时候不再适合对要突出的区域采用遮罩,而是要对突出区域之外进行遮罩处理。暂且称为四周遮罩如下图:
代码实现
实现代码如下:
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. 看不到遮罩效果
这个问题比较大,可能的原因也比较多,可以从以下几点进行排查
- erase函数的参数geom不是Polygon类型。
这个会导致linearRing构造失败,导致内环没添加到polygonRing。linearRing的构造方法,参数是一个Array{ol.coordinate},不能是其他的结构。
如果你的geom不是Polygon类型也没关系,改造erase函数内的代码,使给linearRing构造方法的参数传正确即可。 - 坐标系问题
上面代码中,map对象和测试数据,均采用的是EPSG:4326坐标系(即WGS84)。可以采取其他的坐标系,但是最起码要保证你的map对象的坐标系、图层的坐标系、数据坐标系是一致的。如果不一致,自然没法正常展示。 - 地图中心点不对
可以采用map.getView().fit()方法,传入遮罩的geometry,使地图缩放到遮罩的位置。