javascript - How to download, store and load tiles using Open Layers? - Stack Overflow

I'm creating a PWA using Open Layers. The user must have an option to download the Tiles on the Wi

I'm creating a PWA using Open Layers. The user must have an option to download the Tiles on the Wifi to load them Offline. I read the Open Layers documentation, but, I couldn't find the answer for my problem. The section Tile Cache is empty.

I'm creating a PWA using Open Layers. The user must have an option to download the Tiles on the Wifi to load them Offline. I read the Open Layers documentation, but, I couldn't find the answer for my problem. The section Tile Cache is empty.

Share Improve this question asked Jul 26, 2019 at 19:46 Landinque VonestradLandinque Vonestrad 1991 silver badge10 bronze badges 1
  • 1 OpenLayers 2 had built-in caching to localStorage dev.openlayers/examples/offline-storage.html For caching to sessionStorage or localStorage in more recent versions see stackoverflow./questions/53607810/… – Mike Commented Jul 26, 2019 at 20:19
Add a ment  | 

1 Answer 1

Reset to default 10

You'll need three things for this to work:

  1. An IndexedDB to store tiles
  2. A custom tileLoadFunction for your tile source
  3. A ponent that downloads tiles for a given extent

For (1), you'll want to set up a store, e.g. tiles. The snippet below uses the idb package (https://npmjs./package/idb):

import idb from 'idb';

let indexedDb;

idb.open(this.name, 1, upgradeDb => {
  if (!upgradeDb.objectStoreNames.contains('tiles')) {
    upgradeDb.createObjectStore('tiles');
  }
}).then(db => {
  indexedDb = db;
});

For (2), a starting point could look something like this:

source.setTileLoadFunction(function(tile, url) {
  const tx = db.transaction('tiles', 'readonly');
  tiles = tx.objectStore('tiles');
  const image = tile.getImage();

  tiles.get(url).then(blob => {
    if (!blob) {
      // use online url
      image.src = url;
      return;
    }
    const objUrl = URL.createObjectURL(blob);
    image.onload = function() {
      URL.revokeObjectURL(objUrl);
    };
    image.src = objUrl;
  }).catch(() => {
    // use online url
    image.src = url;
  });
}

For (3), you'll probably want to limit downloading to a small extent. Then, for the chosen extent (in map units) and each zoom level you want to cache, do something like this:

const tilegrid = source.getTileGrid();
const projection = map.getView().getProjection();
const getUrl = source.getTileUrlFunction();
tilegrid.forEachTileCoord(extent, zoom, tilecoord => {
  const url = getUrl(tilecoord, devicePixelRatio, projection);
  fetch(url).then(response => {
    if (response.ok) {
      response.blob().then(blob => {
        const tx = db.transaction('tiles', 'readwrite');
        const tiles = tx.objectStore('tiles');
        tiles.put(url, blob);
      });
    }
  });
});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744358255a4570340.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信