简体   繁体   中英

How to precache tiles with OpenLayers for date animation

I am working on animating an OpenLayers map with multiple layers over a period of time. I would like to precache ol.layer.tile tiles to have smooth transitions between the dates. Any suggestions on how to precache/preload these tiles?

You'll want to rely on your browser cache here. And it requires that your server sends proper cache headers, so the browser does not re-fetch the images with every request. With these prerequisites in mind, proceed as follows:

  1. Call ol.source.TileImage#getTileUrlFunction on your source so you can compute the urls of the tiles you want to cache.

  2. Call ol.source.TileImage#getTileGrid on your source so you can get the tile coordinates for the extent and zoom level you want to cache

  3. Call ol.tilegrid.TileGrid#forEachTileCoord with a function that computes the url for each tile and sets it as src on an image object. When doing so, keep track of the number of loading tiles so you know when you're done.

  4. Repeat the above for all dimensions, after making the respective dimension changes to your source.

In the end, your code for preloading a single dimension could look something like this:

var loadingCount = 0;
var myTileUrlFunction = mySource.getTileUrlFunction();
var myTileGrid = mySource.getTileGrid();
myTileGrid.forEachTileCoord(myExtent, myZoom, function(tileCoord) {
  var url = myTileUrlFunction.call(mySource, tileCoord, ol.has.DEVICE_PIXEL_RATIO, myProjection);
  var img = new Image();
  img.onload = function() {
    --loadingCount;
    if (loadingCount == 0) {
      // ready to animate
    }
  }
  ++loadingCount;
  img.src = url;
}

Solution that gets around cache-preventing headers.

var i = 0;
var renderer = new ol.renderer.canvas.TileLayer(layer);
var tileSource = layer.getSource();
var datePromise = new Promise(function(resolve, reject) {
    tileGrid.forEachTileCoord(extent, currentZ, function(tileCoord) {
        tile = tileSource.getTile(tileCoord[0], tileCoord[1], tileCoord[2], pixelRatio, projection);
        tile.load();
        var loader = function(e) {
            if(e.type === 'tileloadend') {
                --i;
                if(i === 0) {
                    resolve();
                }
            } else {
                 reject(new Error('No response at this URL'));
            }
            /* remove listeners */
            this.un('tileloadend', loader);
            this.un('tileloaderror', loader);
        };
        tileSource.on('tileloadend', loader);
        tileSource.on('tileloaderror', loader);
        ++i;
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM