OpenLayers 6 : Рендеринг карты не происходит при масштабировании

#openlayers #wms #openlayers-6

Вопрос:

Я уже несколько дней повсюду ищу информацию о своей проблеме, но все еще не могу найти хорошее решение этой проблемы.

Мне пришлось выполнить проект с использованием openlayers, чтобы создать карты, которые включены в iframes на сайтах разных городов, чтобы показать некоторую информацию о слоях WMS (статус могил на кладбищах, политика сортировки мусора и т. Д.).

Все работает нормально, за исключением одной вещи. Когда я увеличиваю или уменьшаю масштаб, мое приложение выполняет запрос на получение новых слоев WMS, я вижу, что запрос возвращается с хорошим изображением, но он не отображает карту автоматически, когда запрос возвращается. Он отлично работает при панорамировании или использовании кнопки геолокации.

Мой текущий обходной путь заключается в добавлении 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.0amp;service=WMSamp;request=GetLegendGraphicamp;ogcserver='   config.wmsOgcServer   'amp;sld_version=1.1.0amp;layer='   layer.name   'amp;format=image/pngamp;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>
 

Комментарии:

1. Попробуйте добавить в группу слоев с помощью метода выталкивания коллекции overlayGroup.getLayers().push(imgLayer); Вы не должны нажимать на массив, как указано в openlayers.org/en/latest/apidoc/…

2. @Майк Ну что ж, сэр, вы спасли мне жизнь. Я не знаю, почему я использовал там функцию getArray (), может быть, я пытался решить возникшую у меня проблему и забыл ее удалить, но ваше решение сработало ! Большое спасибо

Ответ №1:

Комментарий @Mike по основному вопросу был решением моей проблемы.

getArray() Функция в overlayGroup.getLayers().getArray().push(imgLayer); моем каждом цикле блокировала отправку событий, как там объяснено : https://openlayers.org/en/latest/apidoc/module-ol_Collection-Collection.html#getArray