即使在拼贴加载并且后期渲染

时间:2018-03-01 17:14:49

标签: javascript canvas printing render openlayers

我正在尝试打印我即时创建的地图。但是,我从地图画布中获取的图像有时看起来有点半:enter image description here

在屏幕截图中,顶部是最终渲染的openlayers地图,底部是我在postrender后从画布中捕获的部分。

我从官方Export PDF example开始,但我正在使用刚刚创建的地图。我记录了瓷砖加载和通过tileloadstart和tileloadend地图事件加载的图块。我还尝试按照postrender合并this answer on stackoverflow事件。加载完所有图块后,我等待postrender事件从画布中捕获地图图像。

问题:

  1. 我认为这个问题与postrender事件提前解决了两个问题有关,我不知道在从画布捕获图像之前等待事件的时间。我开始延迟100毫秒,然后移动到1秒,看起来它工作正常。但是,如果我添加更多图层,我必须将延迟时间设置为3秒才能使其正常运行。所以我不知道对于有很多层的地图应该有什么延迟。

  2. 我也遇到了这样的问题:即使在postrender之后,tileloadstart和tileloadend事件仍会继续触发,因为有些图块尚未加载,即使图块加载计数已经均衡。

  3. 我已经创建了一个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并将错误写入页面顶部时捕获问题。另请注意,行为不一致,您可能需要多次重新加载才能重现。

0 个答案:

没有答案