Openlayers / GeoServer WFS кеширование, тайлы или любая оптимизация - PullRequest
0 голосов
/ 20 февраля 2019

Я разрабатываю веб-приложение с использованием OpenLayers 3.20.0 со слоями, поступающими из GeoServer, связанными с источником данных Oracle.Это приложение использует в основном слой ImageWMS, а также векторный слой для взаимодействия и редактирования.Проблема заключается в том, что карта очень медленная с более чем 30000 нарисованными полилиниями, и я хотел бы ускорить процесс: -)

Поэтому я хотел бы знать, как лучше всего это сделать.Я нашел два способа:

  • изменить свой векторный слой в слое ImageWMS и загрузить необходимые вручную функции только при выделении или редактировании, но это требует определенного количества изменений в моем коде
  • используйте слой VectorTile вместо слоя Vector, думаю, он должен работать как ImageWMS и система листов, чтобы данные загружались только в соответствии с видом карты (хорошо?)

Я посмотрелдля образцов VectorTile, но их не так много (в большинстве случаев речь идет об OpenLayers 2), а документация немного скудна.

Большое неизвестное в объявлении слоя касается источника VectorTile.URL должен быть определен, и я нашел в документации, что я должен поместить параметры {x} / {y} / {z}, но где именно, и как построен этот URL?(см. https://openlayers.org/en/latest/apidoc/module-ol_source_VectorTile-VectorTile.html, параметр 'url')

В качестве примера мой текущий источник Vector имеет URL-адрес, подобный следующему: /geoserver/ANF/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=ANF: myLayer & outputFormat = application% 2Fjson

Итак, чтобы определить источник VectorTile, как мне определить мой URL, и что мне нужно сделать на стороне GeoServer, чтобы правильно настроить мой слой?Я нашел этот ресурс: https://docs.geoserver.org/latest/en/user/extensions/vectortiles/tutorial.html

Единственный векторный формат мозаики, который не является типом изображения на GeoServer, это 'application / json; type = utfgrid'.И когда я помещаю '@ pbf / {z} / {x} / {- y} .pbf' в конце моего URL, как в примере, я получаю ошибки, но я думаю, что это не правильный путь.

Буду признателен за любую помощь, чтобы дать мне больше информации о том, как заставить работать слой и источник VectorTile с GeoServer, или о другом способе оптимизации создаваемой карты.

Большое спасибо.

EDIT

После некоторых ответов я подхожу к этому образцу кода:

this._view = new ol.View({
    center: [74000, 96000],
    projection: 'EPSG:2169',
    zoom: 13,
    maxZoom: 24,
    minZoom: 11
});

this._map = new ol.Map(
    {
        view: this._view,
        controls: [
            new ol.control.Zoom(),
            new ol.control.ScaleLine()
        ]                
    });

let vectorSourceURL: string = `/geoserver/ANF/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=ANF:myLayer&outputFormat=application%2Fjson`;

let source = new ol.source.VectorTile({
    format: new ol.format.GeoJSON({
        defaultDataProjection: 'EPSG:2169',
        geometryName: 'GEOLOC'
    }),
    tileUrlFunction: function (tileCoord, pixelRatio, projection) {
        return vectorSourceURL + '&bbox=' + source.getTileGrid().getTileCoordExtent(tileCoord).join(',') + ',EPSG:2169';
    },
    tileGrid: ol.tilegrid.createXYZ(),
    projection: 'EPSG:2169'
});

let layer = new ol.layer.VectorTile({
    source: source,
    renderOrder: null
});

layer.set('name', 'myLayer');
layer.set('title', 'myLayer');

Этот код приводит к следующей ошибке:

ERROR TypeError: Не удается прочитать свойство 'getUnits' со значением null в ol.renderer.canvas.VectorTileLayer.createReplayGroup_ (ol-debug.js: 29814) в ol.renderer.canvas.VectorTileLayer.drawTileImage (ol-debug.js: 29886) в ol.renderer.canvas.VectorTileLayer.ol.renderer.canvas.TileLayer.prepareFrame (ol-debug.js: 26557) в ol.renderer.canvas.Map.renderFrame (ol-debug.js: 30302) в ol.Map.renderFrame_ (ol-debug.js: 42107) на ol.Map.(ol-debug.js: 41013) в ZoneDelegate.push ../ node_modules / zone.js / dist / zone.js.ZoneDelegate.invokeTask (zone.js: 421) в Object.onInvokeTask (core.js: 3815) вZoneDelegate.push ../ node_modules / zone.js / dist / zone.js.ZoneDelegate.invokeTask (zone.js: 420) в Zone.push ../ node_modules / zone.js / dist / zone.js.Zone.runTask(zone.js: 188)

Похоже, что проблема возникла из EPSG: 2169.Пример с EPSG: 3857 работает хорошо (см. Ответы).

Я что-то упустил?

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Самый простой способ ускорить работу вашего приложения - перейти на использование слоя WMTS (или плиточного WMS).Таким образом, ваше приложение может использовать кеш браузера, чтобы запрашивать только те фрагменты, которые он не видел раньше, и сервер должен отображать их только один раз, поскольку они также кэшируются на диск.

Вам почти наверняка не нужны все 300K-функции для редактирования, поэтому попытка отфильтровать WFS только для ограничивающей рамки запрошенной области.

Наконец, вероятно, самый большой выигрышприходят от перехода к надлежащей пространственной базе данных, такой как PostGIS.

0 голосов
/ 20 февраля 2019

Векторные тайлы не обязательно должны быть .pbf или использовать XYZ URL.Вот пример WFS OpenLayers, переработанный для использования URL-адреса WFS в качестве источника векторных листов.Когда масштаб увеличен до всей Канады, он кажется более отзывчивым, чем исходный пример.

  var vectorSource = new ol.source.VectorTile({
    format: new ol.format.GeoJSON(),
    tileUrlFunction: function(tileCoord, pixelRatio, projection) {
      return 'https://ahocevar.com/geoserver/wfs?service=WFS&' +
          'version=1.1.0&request=GetFeature&typename=osm:water_areas&' +
          'outputFormat=application/json&srsname=EPSG:3857&' +
          'bbox=' + vectorSource.getTileGrid().getTileCoordExtent(tileCoord).join(',') + ',EPSG:3857';
    },
    tileGrid: ol.tilegrid.createXYZ()
  });

  var vector = new ol.layer.VectorTile({
    source: vectorSource,
    style: new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: 'rgba(0, 0, 255, 1.0)',
        width: 2
      })
    })
  });

  var raster = new ol.layer.Tile({
    source: new ol.source.OSM()
  });

  var map = new ol.Map({
    layers: [raster, vector],
    target: document.getElementById('map'),
    view: new ol.View({
      center: [-8908887.277395891, 5381918.072437216],
      maxZoom: 19,
      zoom: 12
    })
  });
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/3.20.0/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/3.20.0/ol.js"></script>
<div id="map"></div>

Кажется, есть проблема с использованием этого кода с проекциями, основанными на proj4, но он должен работать с использованием функции загрузки плитки

let viewProjection = ol.proj.get('EPSG:2169');

let format = new ol.format.GeoJSON({
        defaultDataProjection: viewProjection,
        featureProjection: viewProjection,
        geometryName: 'GEOLOC'
    });

let source = new ol.source.VectorTile({
    tileUrlFunction: function (tileCoord, pixelRatio, projection) {
        return vectorSourceURL + '&bbox=' + source.getTileGrid().getTileCoordExtent(tileCoord).join(',') + ',EPSG:2169';
    },
    tileLoadFunction: function (tile, url) {
        tile.setProjection(viewProjection);
        tile.setLoader(function() {
            var xhr = new XMLHttpRequest();
            xhr.onload = function() {
                tile.setFeatures(format.readFeatures(xhr.responseText));
            }
            xhr.open("GET", url, true);
            xhr.send();
        });
    },
    tileGrid: ol.tilegrid.createXYZ(),
    projection: viewProjection
});
...