Created
August 29, 2023 08:57
-
-
Save patrykkalinowski/45b610532b2710d91f2e39145c0469bf to your computer and use it in GitHub Desktop.
Code to save slippy map tiles to indexedDB as blobs. Uses Dexie
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function lon2tile(lon,zoom) { | |
return (Math.floor((lon+180)/360*Math.pow(2,zoom))) | |
} | |
function lat2tile(lat,zoom) { | |
return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoom))) | |
} | |
async function downloadTile(zoom, column, tile) { | |
let row = await db.tiles.get({ | |
zoom: zoom, | |
column: column, | |
tile: tile | |
}) | |
if (row) { | |
return | |
} | |
let root_url = "https://a.tile.openstreetmap.org/" | |
// TODO: select random subdomain between a, b and c | |
let url = `${root_url}${zoom}/${column}/${tile}.png` | |
let response = await fetch(url); | |
return await response.blob() | |
} | |
async function saveTile(zoom, column, tile, blob) { | |
if (blob) { | |
// add tile only if image blob is in argument | |
await db.tiles.add({ | |
zoom: zoom, | |
column: column, | |
tile: tile, | |
blob: blob | |
}) | |
} | |
// TODO: update progress | |
} | |
export async function getOfflineTileURL(coordinates) { | |
// input: coordinates[zoom, column, tile] | |
let row = await db.tiles.get({ | |
zoom: coordinates[0], | |
column: coordinates[1], | |
tile: coordinates[2] | |
}) | |
if (row) { | |
// if tile image exists in database, return its URL | |
return URL.createObjectURL(row.blob) | |
} else { | |
return | |
// TODO: return URL to online source as backup | |
} | |
} | |
export async function calculateTiles(zoom, north_edge, west_edge, south_edge, east_edge) { | |
var top_tile = lat2tile(north_edge, zoom); // eg.lat2tile(34.422, 9); | |
var left_tile = lon2tile(west_edge, zoom); | |
var bottom_tile = lat2tile(south_edge, zoom); | |
var right_tile = lon2tile(east_edge, zoom); | |
var width = Math.abs(left_tile - right_tile) + 1; | |
var height = Math.abs(top_tile - bottom_tile) + 1; | |
let total_tiles = width * height; // -> eg. 377 | |
for (let c = left_tile; c <= right_tile; c++) { | |
// for each column, get all tiles in this column | |
for (let t = top_tile; t <= bottom_tile; t++) { | |
// for each tile, print URL | |
// console.log(`/${zoom}/${c}/${t}.png`) | |
let image = await downloadTile(zoom, c, t) | |
await saveTile(zoom, c, t, image) | |
// debugging | |
// let tile_url = await getOfflineTileURL([zoom, c, t]) | |
// if (tile_url) { | |
// console.log(tile_url) | |
// // map_store.update(map => { | |
// // map.offline_tile_url = tile_url | |
// // return map | |
// // }); | |
// } | |
} | |
} | |
} | |
for (let zoom = 1; zoom <= 18; zoom++) { | |
calculateTiles(zoom, 50.1, 20, 50, 20.1) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment