在4.6.5的OpenLayers,我需要强制地图视图的刷新在一个循环中,等待刷新在进行循环的下一次迭代之前完成。
对于一些背景:我做的一个关于TileImage源的小多边形界部分重复像素的计算,。我已经能够在一时间让我的计算功能与一个多边形的工作,但是当我试图把它变成一个循环遍历所有的多边形运行,它不会工作,除非整个多边形在地图上都可见图,并且该多边形内的瓦块已被加载。
所以,我现在试图让一个循环来工作,这对每个多边形:
我试着异步功能和承诺玩耍,但不能让它正常工作 - 不管我怎么努力,我forceRefresh函数运行200次(我有200个多边形),然后我所有的瓷砖加载当前视图,然后计算试图为每个多边形,包括那些没有在当前视图。
不幸的是我不能只放大到所有多边形的程度,并从缩放级别运行所有的计算。由于在不同的缩放等级中的像素尺寸的差异,当计算在发言权缩放级别8运行VS缩放水平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”不幸的是不起作用。
使用的不是“postrender” rendercomplete“。这是一个新的事件“渲染时触发完成,即所有来源和瓦片已完成加载当前视口,所有的瓦片被褪”。
https://openlayers.org/en/latest/apidoc/module-ol_render_Event-RenderEvent.html#event:rendercomplete