如何使用少于200MB的内存在Openlayers 3中显示400,000或更多点?

ouk*_*her 6 openlayers-3

我创建了一个独立的地图来为我自己测试一下.我在加载页面时使用Chrome开发者工具对该页面进行了快照,发现它使用的是882MB内存.我想要绘制一小时的闪电数据,我希望用户能够与它进行交互,以便Openlayers在这里有意义.然而,它占用了大量内存,需要一个内存效率更高的解决方案.

以下是我用来执行此操作的代码:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.6.0/ol.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.6.0/ol.css">
  </head>
  <body>

    <div class="container">

      <div class="row">
        <div class="md-12">
          <div id="map" class="map"></div>
        </div>
      </div>
      <div id="span12"> 
      </div>
    </div>


    <script>
var iconInfo = [{
    points: 4,
    radius: 3,
    radius2: 0,
    angle: 0
}, {
    points: 4,
    radius: 3,
    radius2: 0,
    angle: 0
}, {
    points: 4,
    radius: 3,
    radius2: 0,
    angle: 0
}, {
    points: 4,
    radius: 3,
    radius2: 0,
    angle: 0
}];

var i;

var iconCount = iconInfo.length;
var icons = new Array(iconCount);
for (i = 0; i < iconCount; ++i) {
  var info = iconInfo[i];
  icons[i] = new ol.style.RegularShape({
    points: info.points,
    radius: info.radius,
    radius2: info.radius2,
    angle: info.angle,
    fill: new ol.style.Fill({color: 'rgba(0, 0, 0, 0.9)'}),
    stroke: new ol.style.Stroke({width: 2, color: 'rgba(0, 0, 0, 0.9)'}),
  });
}

var featureCount = 350000;
var features = new Array(featureCount);
var feature, geometry;
var e = 25000000;
for (i = 0; i < featureCount; ++i) {
  geometry = new ol.geom.Point(
      [2 * e * Math.random() - e, 2 * e * Math.random() - e]);
  feature = new ol.Feature(geometry);
  feature.setStyle(
      new ol.style.Style({
        image: icons[i % (iconCount - 1)]
      })
  );
  features[i] = feature;
}

var vectorSource = new ol.source.Vector({
  features: features
});
var vector = new ol.layer.Vector({
  source: vectorSource
});


var map = new ol.Map({
  layers: [vector],
  target: document.getElementById('map'),
  view: new ol.View({
    center: [0, 0],
    zoom: 5
  })
});

var overlayFeatures = [];
for (i = 0; i < featureCount; i += 30) {
  var clone = features[i].clone();
  clone.setStyle(null);
  overlayFeatures.push(clone);
}

var featureOverlay = new ol.layer.Vector({
  map: map,
  source: new ol.source.Vector({
    features: overlayFeatures
  }),
  style: new ol.style.Style({
    image: icons[iconCount - 1]
  })
});

map.on('click', function(evt) {
  var info = document.getElementById('info');
  info.innerHTML =
      'Hold on a second, while I catch those butterflies for you ...';

  window.setTimeout(function() {
    var features = [];
    map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
      features.push(features);
      return false;
    });

    if (features.length === 1) {
      info.innerHTML = 'Got one butterfly';
    } else if (features.length > 1) {
      info.innerHTML = 'Got ' + features.length + ' butterflies';
    } else {
      info.innerHTML = 'Couldn\'t catch a single butterfly';
    }
  }, 1);
});

map.on('pointermove', function(evt) {
  if (evt.dragging) {
    return;
  }
  var pixel = map.getEventPixel(evt.originalEvent);
  var hit = map.hasFeatureAtPixel(pixel);
  map.getTarget().style.cursor = hit ? 'pointer' : '';
});

</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

关于如何实现更好的内存效率的任何建议?

Alv*_*tam 11

简短的回答

OpenLayers 3使用大约2 kB每点功能(见下文),因此尽管可能有一些优化,但您必须保持功能数量下降.400,000个功能将需要大约800 MB的内存.

动态加载要素,或使用MultiPoint几何.

将样式从几何图形移动到图层.

更长的答案

样式

当我测试时,从功能中删除样式并将其替换为简单属性会使每个功能的内存占用减少290 B. 见http://jsfiddle.net/vkm2rg46/3/:

var vector = new ol.layer.Vector({
    source: vectorSource,
    style: function (feature, resolution) {
        var i = feature.getProperties().styleId;
        return [new ol.style.Style({
            image: icons[i]
        })];
    }
});
Run Code Online (Sandbox Code Playgroud)

并帮助风格功能:

feature.set('styleId', i % (iconCount - 1));
Run Code Online (Sandbox Code Playgroud)

空间索引

您可以在向量源上将useSpatialIndex设置为false.源保留空间索引以快速检索给定范围内的要素,每个要素似乎需要大约200-250个字节.但是,删除索引可能会对此功能造成严重的性能影响.

减少功能数量##

你最好的选择可能是加载更少的功能.有几种解决方案.

按需加载

最常见的解决方法是让服务器处理数据,并在需要时动态加载.您可能不希望在较低的缩放级别显示40万个点,并且用户不会在任何地方平移.

这可以通过矢量切片或使用bbox或tile的普通矢量源来完成.

它也可以通过在矢量源加载器函数中从您自己的数据集创建特征/几何来完成客户端.

Multipoints

具有10或100个点的MultiPoint几何体几乎不会占用比单个点几何体更多的空间.如果您将闪电击中MultiPoint几何图形,则内存可能不是问题.然而,您会松开一些语义,并且可以将元数据附加到每个单点.

JsFiddle:http://jsfiddle.net/vkm2rg46/8/

内存使用情况

我创建了http://jsfiddle.net/g7qduy1w/3/来测试几何,特征和来源的内存使用情况.您可以在不同阶段拍摄快照(特别是,在向要素添加几何图形时,事件侦听数据会增加,而对要素添加要素时).将简单的点几何添加到没有额外属性的要素并添加到源中,每个要素的内存使用为: 288 B几何事件侦听器
424 B其余几何数据
752 B要素事件侦听器
184 B其余要素数据
261 B来源(使用100 000个功能的总内存份额)