开放图层 6:地图渲染不会在缩放时发生



我已经到处找了好几天了,但仍然找不到一个好的解决方案。

我必须使用openlayers做一个项目,创建包含在不同城市网站iframe中的地图,以显示WMS层的一些信息(墓地中的坟墓状态,垃圾分类政策等)。

一切都很好,除了一件事。当我放大或缩小时,我的应用程序请求获得新的WMS图层,我可以看到请求返回,具有良好的图像,但它不会在请求返回时自动渲染地图。在平移或使用地理定位按钮时,它确实可以完美地工作。

我目前的解决方法是在"moveend"中添加一个map.render()。应用程序的事件,具有可调整的等待请求的延迟。

我使用配置文件来传输地图默认坐标,缩放和图层,所以我想知道问题是否来自于此,因为我的WMS图层都是在每个循环中创建的。

由于该项目的信息是机密的,我必须隐藏所有内容,但这里是我的代码:

scripts.js

$(function () {
//EPSG:2056 definition
proj4.defs('EPSG:2056', '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 ' + '+x_0=2600000 +y_0=1200000 +ellps=bessel ' + '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs');
ol.proj.proj4.register(proj4);
//Initialization for i18next
i18next.init({
lng: config.defaultLanguage,
fallbackLng: config.fallbackLanguage,
supportedLngs: ['fr', 'de', 'en'],
debug: false,
resources: translations
});
//Variables declaration
const popContainer = document.getElementById('popup');
const projectionSwiss = new ol.proj.Projection({
code: 'EPSG:2056',
extent: [2547692.0, 1067417.0, 2681894.0, 1177781.0],
});
const projectionExtent = [2547692.0, 1067417.0, 2681894.0, 1177781.0];
var geolocationOn = false;
var overlayGroup = new ol.layer.Group({
title: i18next.t('layers_overlays_title'),
layers: [],
name: 'overlayGroup'
});
const overlay = new ol.Overlay({
element: popContainer,
autoPan: true,
autoPanAnimation: {
duration: 250,
},
});
var overlayImgs = [];
//Applying page title from config file
$("title").append(config.pageTitle);
//Control and function for geolocation feature
class geolocationControl extends ol.control.Control {
constructor(opt_options) {
const options = opt_options || {};
const button = document.createElement('button');
button.innerHTML = '';
const element = document.createElement('div');
element.className = 'geolocate-btn ol-unselectable ol-control';
element.appendChild(button);
super({
element: element,
target: options.target,
});
button.addEventListener('click', this.geolocationFunc.bind(this), false);
}
geolocationFunc() {
if (!navigator.geolocation) {
alert(i18next.t("geolocation_unsupported"));
return;
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
function onSuccess(position) {
geolocationOn = !geolocationOn;
var {
latitude,
longitude
} = position.coords;
var geolocationCoords = [longitude, latitude];
var geolocationCoords2056 = proj4("EPSG:4326", "EPSG:2056", geolocationCoords);
if (geolocationOn) {
/*$('.geolocate-btn').css('background-color', 'red')*/
$('.geolocate-btn').addClass('ol-control-active');
const geolocationMarker = new ol.Feature();
geolocationMarker.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: '#3399CC',
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: 2,
}),
}),
})
);
geolocationMarker.setGeometry(new ol.geom.Point(geolocationCoords2056));
var geolocationVector = new ol.layer.Vector({
source: new ol.source.Vector({
features: [geolocationMarker],
}),
});
geolocationVector.set('name', 'geolocationCurrent');
map.addLayer(geolocationVector);
}
else {
/*$('.geolocate-btn').css('background-color', 'rgba(255,255,255,.4)')*/
$('.geolocate-btn').removeClass('ol-control-active');
map.getLayers().forEach(function (layer) {
if (layer.get('name') === 'geolocationCurrent') {
map.removeLayer(layer);
}
});
}
}
function onError() {
alert(i18next.t("geolocation_error"));
}
}
}
//Main map declaration
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Group({
title: i18next.t('layers_base_maps_title'),
layers: [
new ol.layer.Tile({
title: i18next.t('layers_base_maps_***'),
type: 'base',
visible: config.baseMaps.***.defaultVisible,
source: newSourceWMTS('***', 'epsg'),
}),
new ol.layer.Tile({
title: i18next.t('layers_base_maps_***'),
type: 'base',
visible: config.baseMaps.***.defaultVisible,
source: newSourceWMTS('***', 'epsg'),
}),
new ol.layer.Tile({
title: i18next.t('layers_base_maps_***'),
type: 'base',
visible: config.baseMaps.***.defaultVisible,
source: newSourceWMTS('***', 'epsg'),
}),
new ol.layer.Tile({
title: i18next.t('layers_base_maps_***'),
type: 'base',
visible: config.baseMaps.***.defaultVisible,
source: newSourceWMTS('***', 'epsg_***'),
})
],
}),
overlayGroup,
],
overlays: [overlay],
view: new ol.View({
projection: projectionSwiss,
extent: projectionExtent,
center: [config.centerX, config.centerY],
zoom: config.defaultZoom,
maxZoom: config.maxZoom,
minZoom: config.minZoom,
}),
controls: ol.control.defaults({
attributionOptions: { collapsible: true, }
}).extend([
new ol.control.FullScreen(),
new ol.control.ScaleLine(),
new ol.control.LayerSwitcher(),
/*new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(2)
}),
new ol.control.ZoomSlider(),*/
new ol.control.Zoom(),
new geolocationControl(),
])
});
//WMS Layers
_.each(_.sortBy(config.wmsLayers, 'zIndex'), function (layer) {
var imgLayer = new ol.layer.Image({
source: new ol.source.ImageWMS({
url: config.wmsUrl,
params: { 'FORMAT': 'image/png', 'LAYERS': layer.name, 'ogcserver': config.wmsOgcServer },
projection: projectionSwiss,
}),
type: 'overlays',
title: '<img src="' + config.wmsUrl + '?version=1.3.0&service=WMS&request=GetLegendGraphic&ogcserver=' + config.wmsOgcServer + '&sld_version=1.1.0&layer=' + layer.name + '&format=image/png&legend_options=fontColor:0xFFFFFF;forceLabels:off"/>',
visible: layer.defaultVisible,
});
imgLayer.set('wmsAttributeGroupId', layer.wmsAttributeGroupId);
overlayGroup.getLayers().getArray().push(imgLayer);
overlayImgs.push(imgLayer);
});
//WMTS Layers
function newSourceWMTS(sourceName, matrixSet) {
return new ol.source.WMTS({
url: 'https://***.***.ch/***/wmts/' + sourceName + '/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png',
cacheSize: 2048,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: [4000, 3750, 3500, 3250, 3000, 2750, 2500, 2250, 2000, 1750, 1500, 1250, 1000, 750, 650, 500, 250, 100, 50, 20, 10, 5, 2, 1.5, 1, 0.5, 0.25, 0.1, 0.05],
matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
}),
format: 'image/png',
matrixSet: matrixSet,
wrapX: true,
requestEncoding: 'REST',
attributions: i18next.t("layers_base_maps_attributions"),
})
};
//Popup on click
map.on('singleclick', function (evt) {
var element = overlay.getElement();
$(element).popover('dispose');
_.each(overlayImgs, function (l) {
if (l.getVisible() === true) {
var coord = evt.coordinate;
var viewResolution = map.getView().getResolution();
var url = l.getSource().getFeatureInfoUrl(coord, viewResolution, projectionSwiss, { 'INFO_FORMAT': 'application/vnd.ogc.gml' });
$.get(url, function (xmlData) {
workingData = $($.parseXML(xmlData));
var description = '';
var title = '';
var wmsAttributeGroup = _.find(config.wmsAttributeGroups, function (ga) { return ga.id === l.get('wmsAttributeGroupId') });
if (wmsAttributeGroup) {
var referenceAttribute = workingData.find(wmsAttributeGroup.referenceAttribute);
if (referenceAttribute.length > 0) {
var popupTitle = '';
var popupContent = '';
_.each(wmsAttributeGroup.attributes, function (attribute) {
var attributeValue = workingData.find(attribute.name).text();
if (attribute.isTitle) {
popupTitle += '<h5>' + attributeValue + '</h5> ';
} else {
if (attributeValue !== '') {
if (attribute.display) {
popupContent += attribute.name.charAt(0).toUpperCase() + attribute.name.slice(1) + ' : ';
}
popupContent += attributeValue + '<br/>';
}
}
});
if (popupContent !== '') {
overlay.setPosition(evt.coordinate);
$(element).popover({
'placement': 'top',
'animation': true,
'html': true,
'content': popupContent,
'title': popupTitle,
});
$(element).popover('show');
}
}
}
});
}
});
});
map.on('moveend', function () {
var element = overlay.getElement();
$(element).popover('dispose');
setTimeout(function () {
map.render();
}, config.renderTime);
});
//Translating buttons titles
$('.geolocate-btn button').prop('title', i18next.t('btn_geolocation_title'));
$('.ol-full-screen-false').prop('title', i18next.t('btn_fullscreen_title'));
$('.layer-switcher button').prop('title', i18next.t('btn_layers_title'));
$('.ol-attribution button').prop('title', i18next.t('btn_attributions_title'));
$('.ol-zoom-in').prop('title', i18next.t('btn_zoomin_title'));
$('.ol-zoom-out').prop('title', i18next.t('btn_zoomout_title'));
//Remove default text from controls
$('.ol-zoom-in').text("");
$('.ol-zoom-out').text("");
$('.ol-full-screen-false').text("");
$('.ol-full-screen-true').text("");
$('.ol-attribution button').text("");
});

config.js

let config = {
//Availables languages : fr, de, en
defaultLanguage: 'fr',
fallbackLanguage: 'fr',
//Title of the page on the browser
pageTitle: 'Default',
//Coordinates of the center of the map, use EPSG:2056 standard
centerX: ***,
centerY: ***,
//Default zoom and limits
defaultZoom: 11,
maxZoom: 16,
minZoom: 0,
//Time between the WMS request and the render of the map
renderTime: 1000,
//Set default map, only one map can be set to true
baseMaps: {
***: { defaultVisible: false },
***: { defaultVisible: false },
***: { defaultVisible: false },
***: { defaultVisible: true }
},
//WMS Config
wmsUrl: 'https://***.***.ch/***/***/***',
wmsOgcServer: 'source for None',
wmsLayers: [
{ name: '***', defaultVisible: true, zIndex: -1, wmsAttributeGroupId: 1 },
{ name: '***', defaultVisible: true, zIndex: -1, wmsAttributeGroupId: -1 },
{ name: '***', defaultVisible: true, zIndex: -1, wmsAttributeGroupId: -1 },
{ name: '***', defaultVisible: true, zIndex: -1, wmsAttributeGroupId: -1 },
{ name: '***', defaultVisible: true, zIndex: -1, wmsAttributeGroupId: -1 },
],
wmsAttributeGroups: [
{
id: 1, referenceAttribute: '***', attributes: [
{ name: '***', display: true, isTitle: true },
{ name: '***', display: false, isTitle: false },
]
}
],
}

index . html

<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<meta http-equiv="cache-control" content="no-cache">
<title></title>
<!-- CSS styling-->
<link rel="stylesheet" href="js/lib/openlayers/css/ol.css" type="text/css">
<link rel="stylesheet" href="js/lib/bootstrap/dist/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="js/lib/ol-layerswitcher/src/ol-layerswitcher.css" type="text/css">
<link rel="stylesheet" href="css/styles.css" type="text/css">
<link rel="icon" href="favicon.ico" />
<!-- JS libraries -->
<script src="js/lib/i18next/i18next.js"></script>
<script src="js/lib/jquery/dist/jquery.js"></script>
<script src="js/lib/proj4/dist/proj4.js"></script>
<script src="js/lib/openlayers/build/ol.js"></script>
<script src="js/lib/underscore/underscore.js"></script>
<script src="js/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/lib/ol-layerswitcher/dist/ol-layerswitcher.js"></script>
<!-- Configs -->
<script src="js/config.js"></script>
<script src="js/translate.js"></script>

<body>
<div id="map" class="map"></div>
<div id="popup"></div>
<script src="js/scripts.js"></script>
<a href="https://***.***.ch" target="_blank">
<div id="logo" class="logo-img"></div>
</a>
</body>

</html>

@Mike对主要问题的评论是我问题的解决方案。

每个循环中overlayGroup.getLayers().getArray().push(imgLayer);中的getArray()函数阻塞了事件调度,如下所述:https://openlayers.org/en/latest/apidoc/module-ol_Collection-Collection.html#getArray