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
1 Answer
Reset to default 10You'll need three things for this to work:
- An IndexedDB to store tiles
- A custom
tileLoadFunction
for your tile source - 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条)