javascript - 平移 500 个特征时 OpenLayers 3 性能低下

标签 javascript performance svg html5-canvas openlayers-3

我正在构建一个应用程序,用于将特征映射到描绘平面图的图像层(使用 OL 的 ImageStatic 层)。每个功能都有一个 svg 图标作为样式,并且可能有额外的 svg 图标作为边缘的“徽章”。

我在 this jsfiddle 中设置了代码相关部分的简化版本.

var map = new ol.Map({
  layers: [],
  interactions: ol.interaction.defaults({}),
  target: "map"
});

var pixelProjection = new ol.proj.Projection({
    code: 'pixel',
    units: 'pixels',
    extent: [0, 0, 4097, 1596]
  }),
  // create layer
  floorMapLayer = new ol.layer.Image({
    source: new ol.source.ImageStatic({
      url: "https://sunriverassistedliving.com/wp-content/uploads/Main-Floor-Plan.jpg",
      imageSize: [4097, 1596],
      projection: pixelProjection,
      imageExtent: pixelProjection.getExtent()
    })
  }),
  // create view
  floorMapView = new ol.View({
    projection: pixelProjection,
    center: [2000, 750] || ol.extent.getCenter(pixelProjection.getExtent()),
    zoom: 1
  }),
  poiSource = new ol.source.Vector({
    features: []
  }),
  vectorLayer = new ol.layer.Vector({
    source: poiSource
  }),
  layerGroup = new ol.layer.Group({
    layers: [floorMapLayer, vectorLayer]
  });

map.setView(floorMapView);
map.setLayerGroup(layerGroup);

var iconStyle = new ol.style.Icon( /** @type {olx.style.IconOptions} */ ({
  anchor: [0.5, 1],
  anchorXUnits: 'fraction',
  anchorYUnits: 'fraction',
  size: [25, 25],
  imageSize: [25, 25],
  src: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB3aWR0aD0iMjUiIGhlaWdodD0iMjUiIGlkPSJzdmczNjQ4Ij4KICA8ZGVmcyBpZD0iZGVmczM2NTAiLz4KICA8cGF0aCBkPSJNIDEyLjUxNDksNC45NmUtMDA3IEMgNS42MTE3NCw0Ljk2ZS0wMDcgMCw1LjU4MTk0MDUgMCwxMi40ODUxIEMgMCwxOS4zODgyNiA1LjYxMTc0LDI1IDEyLjUxNDksMjUgQyAxNS4yNzY5NCwyNSAxNy44MDQ4LDI0LjA3NDg5IDE5Ljg3NDg1LDIyLjU1NjYyIEwgMTIuNTQ0NywxNy4xOTMwOSBMIDUuMjE0NTQsMjIuNTg2NDEgTCA4LjA0NTI5LDEzLjk0NTE3IEwgMC42NTU1NCw4LjY3MTA0MDUgTCA5Ljc0MzczOTUsOC42NzEwNDA1IEwgMTIuNDg1MSwwLjAyOTgwMDUgTCAxNS4yODYwNSw4LjY3MTA0MDUgTCAyNC4zNDQ0NTksOC42MTE0NDA1IEwgMTcuMDE0MywxMy45MTUzOCBMIDE5Ljg3NDg1LDIyLjU1NjYyIEMgMjIuOTc4NDc5LDIwLjI4MDI4IDI1LDE2LjYyNjIyIDI1LDEyLjQ4NTEgQyAyNSw1LjU4MTk0MDUgMTkuNDE4MDYsNC45NmUtMDA3IDEyLjUxNDksNC45NmUtMDA3IHogIi8+Cjwvc3ZnPg=="
}));

var styleCache = {};

var customStyleFunctions = [
  function(resolution) {
    var style = new ol.style.Style({
      image: new ol.style.Icon(({
        anchor: [1, 2],
        anchorXUnits: 'fraction',
        anchorYUnits: 'fraction',
        size: [15, 15],
        imageSize: [15, 15],
        src: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB3aWR0aD0iMjUiIGhlaWdodD0iMjUiIGlkPSJzdmczNjQ4Ij4KICA8ZGVmcyBpZD0iZGVmczM2NTAiLz4KICA8cGF0aCBkPSJNIDEyLjUxNDksNC45NmUtMDA3IEMgNS42MTE3NCw0Ljk2ZS0wMDcgMCw1LjU4MTk0MDUgMCwxMi40ODUxIEMgMCwxOS4zODgyNiA1LjYxMTc0LDI1IDEyLjUxNDksMjUgQyAxNS4yNzY5NCwyNSAxNy44MDQ4LDI0LjA3NDg5IDE5Ljg3NDg1LDIyLjU1NjYyIEwgMTIuNTQ0NywxNy4xOTMwOSBMIDUuMjE0NTQsMjIuNTg2NDEgTCA4LjA0NTI5LDEzLjk0NTE3IEwgMC42NTU1NCw4LjY3MTA0MDUgTCA5Ljc0MzczOTUsOC42NzEwNDA1IEwgMTIuNDg1MSwwLjAyOTgwMDUgTCAxNS4yODYwNSw4LjY3MTA0MDUgTCAyNC4zNDQ0NTksOC42MTE0NDA1IEwgMTcuMDE0MywxMy45MTUzOCBMIDE5Ljg3NDg1LDIyLjU1NjYyIEMgMjIuOTc4NDc5LDIwLjI4MDI4IDI1LDE2LjYyNjIyIDI1LDEyLjQ4NTEgQyAyNSw1LjU4MTk0MDUgMTkuNDE4MDYsNC45NmUtMDA3IDEyLjUxNDksNC45NmUtMDA3IHogIi8+Cjwvc3ZnPg=="
      }))
    });
    return [style];
  }
];

var defaultStyleFunction = function(resolution) {
  var feature = this;
  this.set('manuallyHidden', false);

  if (!feature.get('selected') && (feature.get('hidden') || feature.get('manuallyHidden'))) {

    // use hidden marker style
    if (!styleCache.hidden) {
      styleCache.hidden = new ol.style.Style({});
    }
    return [styleCache.hidden];
  }

  // draw marker normally
  var iconSrc = iconStyle.getSrc();
  if (!styleCache[iconSrc]) {
    styleCache[iconSrc] = new ol.style.Style({
      image: iconStyle,
    });
  }

  var styles = [styleCache[iconSrc]];

  // add styles from registered overlay style functions
  for (var i = 0; i < customStyleFunctions.length; i++) {
    //console.log(customStyleFunctions[i]);
    styles = styles.concat(customStyleFunctions[i](resolution));
  }

  return styles;
};

for (var i = 0; i < 500; i++) {
  var posX = Math.random() * 4097;
  var posY = Math.random() * 1596;
  var feature = new ol.Feature({
    geometry: new ol.geom.Point([posX, posY]),
  });
  feature.setStyle(defaultStyleFunction);

  poiSource.addFeature(feature);
}

有 500 个功能,每个功能都有一个徽章。平移 map 感觉不稳定,Chrome 中的时间轴注意到帧速率下降到 5 fps 左右。

Chrome Timeline

这仍然有点可用,但在我的实际应用中,情况要糟糕得多,即使只使用大约 100 个特征,每个特征有 1-2 个徽章,也会完全卡住。我无法缩小我的实际应用程序响应不如此演示的原因,但探查器没有注意到任何其他正在运行的代码,而不是 OpenLayers 中的渲染和 GPU 正在忙着喘气。不过,我实际应用测试中的底层图像要大得多。大约 10000x7000px(jsfiddle 大约 4000x1600px)。这当然会渲染一个巨大的 Canvas ,需要重新绘制资源。

我想知道 OpenLayers 中是否有任何其他性能提升可以用来提高 map 平移的响应速度?我在装有最新 Google Chrome/Firefox 的 2011 年末 13 英寸 MacBook Pro 上使用 3.15.1 版。

最佳答案

静态图像层应该不是问题。但是您正在以非常低效的方式为矢量图层使用样式函数。不要在每次调用样式函数时都创建一个新的样式实例。相反,在外部创建样式并且只让您的样式函数返回它。另外,最好在图层上设置一个样式函数,而不是在每个特征上都设置一个。

关于javascript - 平移 500 个特征时 OpenLayers 3 性能低下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39125958/

相关文章:

javascript - d3 : Path data generator and if-statement

javascript - 如何使用 D3 加载 csv、显示表格并在 javascript 中使用 bootstrap 设置样式

javascript - 雪花中的 ARRAY_REMOVE()?

objective-c - 查找 NSDictionary 键的更简单方法?

performance - 从具有增强性能的文本文件中删除重复出现的行

javascript - 检查 svg 元素是否在 View 框内

javascript - 新的 Backbone 实例属性指向旧实例属性

javascript - 点击 map 外部打开 Google map 信息窗口

sql - 散列连接和合并连接 (Oracle RDBMS) 之间有什么区别?

html - 带有 HTML5 视频文本填充的 SVG