openlayers 5 раздражает флеш на vector.getSource().clear()

Когда я загружаю более 500 векторных функций в Openlayers, производительность на планшетах и ​​телефонах сильно снижается. Мое решение состояло в том, чтобы очистить источник на карте moveend событие. Это работает, но приводит к раздражающей вспышке, предположительно между очисткой и перезагрузкой источника.

Более раннее решение этой "перепрошивки" здесь больше не работает, оно приводит к рекурсивным вызовам WFS.

Вот мой текущий код:

import {GeoJSON} from 'ol/format';
import {bbox as bboxStrategy} from 'ol/loadingstrategy.js';
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector';

var vectorSource = new VectorSource({
 format: new GeoJSON({ dataProjection: layerProjection }),
 loader: function(extent, resolution, projection) {
   var proj = projection.getCode();
   var url = 'https://xxx.xxx/geoserver/wfs?service=WFS' +
     '&version=1.1.0&request=GetFeature&typename=' + layer + 
     '&maxFeatures=200&outputFormat=application/json&srsname=' + proj +
     '&bbox=' + extent.join(',') + ',' + proj;
   var xhr = new XMLHttpRequest();
   xhr.open('GET', url);
   var onError = function() {
     vectorSource.removeLoadedExtent(extent);
   }
   xhr.onerror = onError;
   xhr.onload = function() {
     if (xhr.status == 200) {
       //vectorSource.clear();// Causes recursion          
       vectorSource.addFeatures(
         vectorSource.getFormat().readFeatures(xhr.responseText));
     } else {
       onError();
     }
   }
   xhr.send();
 },
 strategy: bboxStrategy
});

var vector = new VectorLayer({
  source: vectorSource,
  style: style,
  visible: visible
});
map.on('moveend', function(evt) {
  console.log('refreshing vector');
  vectorSource.clear()
});

Есть ли способ избежать сброса / перезагрузки флэш-памяти в Openlayers 5? Или есть другой метод, который я должен использовать для загрузки векторных слоев (у меня обычно есть точечные слои с 5000 до 10000 объектов).

[EDIT] После комментария от @ahocevar вот стиль, который я использую:

import {Style, Circle, Fill, Stroke} from 'ol/style';
import Defaults from './PointDefaults';

export default function() {
  return new Style({
    image: new Circle({
      radius: Defaults.radius,
      fill: new Fill({
        color: 'green',
      }),
      stroke: new Stroke({
        color: Defaults.strokeColor,
        width: Defaults.strokeWidth
      })
    }),
  });
}

3 ответа

Не очищайте источник на каждом шаге, но только когда он превышает количество функций max, это предотвратит слишком частые перезагрузки:

map.on('moveend', function(evt) {
  if (vectorSource.getFeatures().length > max) {
    vectorSource.clear()
  }
});

Openlayers должен отображать более 500 функций даже на медленных устройствах.

  • Как говорит Ахочевар, стиль может быть задействован, давайте посмотрим, как вы его используете.
  • Вы также можете попробовать использовать renderMode: 'image' опция для векторного слоя для более быстрой визуализации во время взаимодействия и анимации.
  • Вы можете использовать кластеризацию в больших масштабах, чтобы уменьшить количество объектов для рисования.

Например, этот сайт отображает более 18 000 точечных функций даже на мобильных устройствах: https://c-conforme.fr/

Проблема в том, что вы создаете новый Style с новым Circle изображение для каждой функции в каждом кадре рендеринга. В вашем случае вам даже не нужна функция стиля, потому что стиль одинаков для всех функций. Так что ваши style модуль должен экспортировать стиль, а не функцию, которая возвращает стиль:

import {Style, Circle, Fill, Stroke} from 'ol/style';
import Defaults from './PointDefaults';

export default new Style({
  image: new Circle({
    radius: Defaults.radius,
    fill: new Fill({
      color: 'green',
    }),
    stroke: new Stroke({
      color: Defaults.strokeColor,
      width: Defaults.strokeWidth
    })
  })
});

Спустя 2 года я нашел решение, которое не очень «яркое», но немного (я думаю, что моя формулировка вопроса, должно быть, была слишком расплывчатой).

я использую vectorSource.refresh()

Давая это:

      map.on('moveend', function(evt) {
 console.log('refreshing vector');
 vectorSource.refresh()
});

Версия OpenLayers, которую я сейчас использую, — v6.5.0.

Другие вопросы по тегам