我正在尝试打印我即时创建的地图。但是,我从地图画布中获取的图像有时看起来有点半:
在屏幕截图中,顶部是最终渲染的openlayers地图,底部是我在postrender后从画布中捕获的部分。
我从官方Export PDF example开始,但我正在使用刚刚创建的地图。我记录了瓷砖加载和通过tileloadstart和tileloadend地图事件加载的图块。我还尝试按照postrender合并this answer on stackoverflow事件。加载完所有图块后,我等待postrender事件从画布中捕获地图图像。
问题:
我认为这个问题与postrender事件提前解决了两个问题有关,我不知道在从画布捕获图像之前等待事件的时间。我开始延迟100毫秒,然后移动到1秒,看起来它工作正常。但是,如果我添加更多图层,我必须将延迟时间设置为3秒才能使其正常运行。所以我不知道对于有很多层的地图应该有什么延迟。
我也遇到了这样的问题:即使在postrender之后,tileloadstart和tileloadend事件仍会继续触发,因为有些图块尚未加载,即使图块加载计数已经均衡。
我已经创建了一个codepen来演示这个问题: Print map using tile loading and postrender events
var bingKey = ""; // Please enter a bing key
var exportButton = document.getElementById("prepareMap");
exportButton.addEventListener("click", function() {
exportButton.disabled = true;
document.body.style.cursor = "progress";
prepareMap();
});
var map;
var mapCanvas;
var printDelayAfterLoad = 100;
var loading;
var loaded;
var allLoaded;
var prepareMap = function() {
loading = 0;
loaded = 0;
allLoaded = false;
var raster = new ol.layer.Tile({
source: new ol.source.OSM(),
opacity: 0.7
});
var bingLayer = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: bingKey,
imagerySet: "Aerial"
})
});
var mapLayers = [bingLayer, raster];
map = new ol.Map({
layers: mapLayers,
target: "map",
controls: ol.control.defaults({
attributionOptions: {
collapsible: false
}
}),
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
for (var i = 0; i < mapLayers.length; i++) {
var layerSource = mapLayers[i].getSource();
layerSource.on("tileloadstart", tileLoadStart);
layerSource.on("tileloadend", tileLoadEnd);
layerSource.on("tileloaderror", tileLoadEnd);
}
map.renderSync();
};
var tileLoadStart = function() {
++loading;
if (allLoaded) {
logExtraTilesLoadError();
}
};
var tileLoadEnd = function() {
++loaded;
if (loading === loaded) {
allLoaded = true;
listenToPostRender();
}
};
var alreadyPrinted = false;
var listenToPostRender = function() {
map.once("postrender", function() {
if (!alreadyPrinted) {
console.log("postrender called");
window.setTimeout(function() {
printMap();
}, printDelayAfterLoad);
alreadyPrinted = true;
}
});
// listening to postcompose just to capture the mapCanvas from the event
map.once("postcompose", function(event) {
console.log("postcompose called");
mapCanvas = event.context.canvas;
});
};
var printMap = function() {
console.log("printMap called");
var data = mapCanvas.toDataURL("image/png");
var mapImageElement = document.getElementById("mapImage");
mapImageElement.setAttribute("src", data);
cleanUp();
};
var cleanUp = function() {
console.log("cleanUp called");
//exportButton.disabled = false;
document.body.style.cursor = "auto";
};
var errorMessage =
" more tiles loaded after initially all tiles had been loaded";
var extraTileLoadCount = 0;
var logExtraTilesLoadError = function() {
extraTileLoadCount++;
var errorsDiv = document.getElementById("errorsDiv");
errorsDiv.innerHTML = extraTileLoadCount + errorMessage;
console.error("errorMessage");
};
您需要在javascript文件的顶部输入Bing Maps Key。 Bing Map Key可以从https://www.bingmapsportal.com/生成。使用BingMap图层,问题可以更加一致地重现。在代码笔中,我还在postrender之后调用tileloadstart并将错误写入页面顶部时捕获问题。另请注意,行为不一致,您可能需要多次重新加载才能重现。