在OpenLayers 4.6.5中,我需要在循环中强制刷新地图视图,并等待刷新完成,然后再进行循环的下一次迭代。
对于某些情况:我正在对TileImage源的小多边形边界部分进行重复像素计算。我已经能够一次让一个多边形使用我的计算功能,但是当我尝试将其放入循环以遍历所有多边形时,除非整个多边形在地图上可见,否则它将无法工作视图,并且多边形内的图块已加载。
所以我现在正试图使每个多边形工作的循环:
我尝试使用异步函数和promise,但无法使其正常工作-无论如何尝试,我的forceRefresh函数都会运行200次(我有200个多边形),然后加载所有图块对于当前视图,然后尝试对每个多边形(包括不在当前视图中的那些多边形)进行计算。
不幸的是,我不能只缩放到所有多边形的范围并从该缩放级别运行所有计算。由于不同缩放级别下像素大小的差异,因此在以缩放级别8与缩放级别14进行计算时,结果会有很大差异。
这些是我代码的相关部分:
function forceRefresh(source,ms) {
return new Promise(resolve => {
source.refresh();
map.updateSize();
setTimeout(() => {
resolve('Map should now be refreshed');
}, ms);
});
}
async function getCellAverage(featureID,equation,calcZoom=14) {
return new Promise(resolve => {
initialZoom = view.getZoom();
initialCenter = view.getCenter();
layerSource = window["layer" + featureID].getSource();
window["allTilesLoaded"] = false;
zoomToFit("source"+featureID);
if(view.getZoom() > calcZoom) {
view.setZoom(calcZoom);
}
layerSource.getFeatures().forEach(async function(feature) {
var result = await forceRefresh(window['L8SourceNRG'],100);
console.log(result);
var geom = feature.getGeometry();
var size = map.getSize();
var ndviArray = [];
map.addEventListener('postrender', function() {
if(window['L8SourceNRG'].allTilesLoaded == true) {
console.log('Confirmed all L8SourceNRG tiles loaded');
map.removeEventListener('postrender');
if (geom.intersectsExtent(map.getView().calculateExtent(size))) {
for (var i=0; i<size[0]; i++) {
for (var j=0; j<size[1]; j++) {
var coordinate = map.getCoordinateFromPixel([i,j]);
if (geom.intersectsCoordinate(coordinate)) {
let tileCoord = L8SourceTileGrid.getTileCoordForCoordAndResolution(coordinate, map.getView().getResolution());
let key = tileCoord.join('-');
if (key in window['tiles']) {
let origin = L8SourceTileGrid.getOrigin(tileCoord[0]);
let res = L8SourceTileGrid.getResolution(tileCoord[0]);
let tileSize = L8SourceTileGrid.getTileSize(tileCoord[0]);
var w = Math.floor(((coordinate[0] - origin[0]) / res) % (tileSize[0] | tileSize));
var h = Math.floor(((origin[1] - coordinate[1]) / res) % (tileSize[1] | tileSize));
var canvas = document.createElement("canvas");
canvas.width = tiles[key].width;
canvas.height = tiles[key].height;
var ctx = canvas.getContext("2d");
ctx.drawImage(tiles[key], 0, 0);
let img = ctx.getImageData(0, 0, canvas.width, canvas.height);
let imgData = img.data;
let index = (w + h * 256) * 4;
let pixel = [imgData[index + 0], imgData[index + 1], imgData[index + 2], imgData[index + 3]];
ndviArray.push((( pixel[0] - pixel[1] ) / ( pixel[0] + pixel[1] )));
}
}
}
}
}
var ndviSum = ndviArray.reduce((a, b) => a + b, 0);
var ndviAvg = ndviSum / ndviArray.length;
console.log("Average NDVI: "+ndviAvg);
makePolygonMask("avgNDVI",featureID,geom,ndviAvg);
window['cellAverageDone'] = true;
}
});
});
setTimeout(() => {
resolve('resolved');
}, 100);
});
}
async function getAllAverages(equation) {
map.getLayers().forEach(async function(layer) {
window['cellAverageDone'] = false;
if (layer.get('type') == "cell") {
layerID = layer.get('name').substring(9);
var result = await getCellAverage(layer.get('name').substring(5),'NDVI');
}
});
}
“ allTilesLoaded”属性由一个辅助函数设置,为简便起见,我省略了它,因为我认为它与此处的问题无关。
控制台中的输出如下:
(200x) Map should now be refreshed
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.37295137830077313
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.38384215219470413
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.44356048105512613
...
Confirmed all L8SourceNRG tiles loaded
Average NDVI: NaN
上面的最后一行显示了尝试计算当前视图之外的多边形时发生的情况。
我希望看到以下内容:
Map should now be refreshed
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.37295137830077313
Map should now be refreshed
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.38384215219470413
Map should now be refreshed
Confirmed all L8SourceNRG tiles loaded
Average NDVI: 0.44356048105512613
...
编辑:请注意,我正在OL 4.6.5中工作,因此不幸的是,“ rendercomplete”不起作用。
答案 0 :(得分:1)
使用“ rendercomplete”代替“ postrender”。这是一个新事件,“在渲染完成时触发,即所有源和图块均已完成当前视口的加载,并且所有图块都被淡入。”
https://openlayers.org/en/latest/apidoc/module-ol_render_Event-RenderEvent.html#event:rendercomplete