OL3 ImageCanvas renderFunction性能不佳

时间:2016-04-19 09:29:45

标签: javascript canvas openlayers-3

所以我正在尝试使用Esri opensource example (windy.js)并使用类似于the OL3 D3 example的内容在OpenLayers 3上呈现它。

windy.js 在画布上呈现风动画地图。画布大小似乎不会改变渲染性能。

首先,我将windy.js渲染到画布并每隔0.5秒更新一次:

g_windy = new Windy({
    canvas: $("#canvas")[0],
    data: //Some data
});
//map is an OL3 Map object
function redraw() {
  windy.stop();

  setTimeout(function() {
    var mapSize = map.getSize();
    var extent = map.getView().calculateExtent(mapSize);

    extent = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326');

    var canvas_bounds = [
        [0,0],
        [mapSize[0]*2, mapSize[1]*2]
      ]; 

      var map_projected_bounds = [
        [
          extent[0],
          extent[1]
        ],
        [
          extent[2],
          extent[3]
        ]
      ];

    windy.start(
      canvas_bounds,
      mapSize[0]*2, mapSize[1]*2, 
      map_projected_bounds
    );
  }, 500);
}

redraw();

我的 canvasFunction 实现引用了windy.js呈现并返回它的画布:

var canvasFunction = function(extent, resolution, pixelRatio, size, projection) {
  canvas = $("canvas#canvas")[0];
  canvas.setAttribute('width', map.getSize()[0]*4);
  canvas.setAttribute('height', map.getSize()[1]*4);
  return canvas;
};

我现在将图层添加到地图中:

var canvasLayer = new ol.layer.Image({
  source: new ol.source.ImageCanvas({
    canvasFunction: canvasFunction,
    projection: 'EPSG:3857',
    ratio: 1
  })
});

map.addLayer(canvasLayer);
map.getView().on('change:center', redraw);
map.getView().on('change:resolution', redraw);

//Next I update my map to rerender at a fast interval. Note that having 1 millisecond vs 60 frames/second does not change performace.
setInterval(function() { map.updateSize();}, 1);

我的结果在地图上为我提供了 windy.js 图层,但我遇到了一个问题:

  • windy.js画布没有性能问题并且运行顺畅,但是在较高的画布/地图尺寸下,OL3层非常滞后。

复制画布并不是我们想要实现的完美实现,但是从OL3执行pull-request并添加可支持此功能的功能更有效。

1 个答案:

答案 0 :(得分:1)

因为我是这些风图的忠实粉丝,所以我忍不住试一试。

与D3示例的​​主要区别在于,D3画布是静态的,只有在地图范围发生变化时才需要更新。 Windy.js运行自己的动画循环,不断更新。首先windy.js绘制到自己的画布中,然后ol3必须将此画布绘制到地图上。也许这种技术可以优化,但我建议采用不同的方法:

创建一个canvasy元素,windy.js可以在其中绘制。在它旁边为OpenLayers创建一个div元素:

<div id="map" class="map">
  <canvas id="windyMap" class="fill"></canvas>
  <div id="olMap" class="fill"></div>
</div>

使用一些CSS线将画布定位在地图div上方,并确保事件仍然传递(pointer-events: none)。每次平移/缩放地图时,重新启动windy.js动画。就是这样。

Demo - Code