代码之家  ›  专栏  ›  技术社区  ›  minisaurus

openlayers 5恼人的flash开启向量.getSource().清除()

  •  2
  • minisaurus  · 技术社区  · 6 年前

    当我在Openlayers中加载超过500个矢量特性时,平板电脑和电话的性能会严重下降。我的解决办法是清除地图上的源头 moveend 事件。这是可行的,但会导致恼人的闪光,大概是在源代码的清除和重新加载之间。

    这种“闪现”的早期解决方案 here 不再工作,它会导致对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个特征的点层)。

    [编辑]在@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
          })
        }),
      });
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Viglino Jean-Marc    6 年前

    不要清除每个moveend上的源,但仅当其超过多个功能时 max

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

    Openlayers应该能够显示超过500个特性,即使在速度较慢的设备上也是如此。

    • 正如ahocevar所说的风格可能涉及到让我们看看你如何使用它。
    • 您也可以尝试使用 renderMode: 'image' 用于矢量层的选项,用于在交互和动画期间更快地渲染。
    • 您可以大规模使用聚类来减少要绘制的特征的数量。

    例如,即使在移动设备上,该网站也显示超过18000点的功能: https://c-conforme.fr

        2
  •  1
  •   ahocevar    6 年前

    问题是你正在创建一个新的 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
        })
      })
    });