Offline-Karten: POI-Marker offlinetauglich + Offline-Banner klappt ein (Geraetetest-Befunde)
- MapOffline.downloadAround speichert zusaetzlich /api/osm/pois je Typ fuer die Region-Bbox in IndexedDB (Key-Praefix p/, Merge per id — zweite Region loescht die erste nicht); MapOffline.pois(type,bbox) filtert fuer den Ausschnitt - map.js Phase-1-Fallback: Fetch fehlgeschlagen (offline) -> gespeicherte Region-POIs statt leerer Karte; Download-Toast zeigt Marker-Anzahl - Offline-Banner: nach 5s auf schmale Icon-Leiste eingeklappt (verdeckte die Karten-Legende); Inline-Styles nach components.css konsolidiert - Bump v1223
This commit is contained in:
parent
c5bdad2d86
commit
e2c75f04bc
9 changed files with 106 additions and 37 deletions
|
|
@ -77,11 +77,14 @@ window.MapOffline = (function () {
|
|||
var r = lat * Math.PI / 180;
|
||||
return Math.floor((1 - Math.log(Math.tan(r) + 1 / Math.cos(r)) / Math.PI) / 2 * Math.pow(2, z));
|
||||
}
|
||||
function _tileList(lat, lon, radiusKm) {
|
||||
function _bboxAround(lat, lon, radiusKm) {
|
||||
var dLat = radiusKm / 111, dLon = radiusKm / (111 * Math.cos(lat * Math.PI / 180));
|
||||
var w = lon - dLon, e = lon + dLon, s = lat - dLat, n = lat + dLat, list = [];
|
||||
return { south: lat - dLat, west: lon - dLon, north: lat + dLat, east: lon + dLon };
|
||||
}
|
||||
function _tileList(lat, lon, radiusKm) {
|
||||
var b = _bboxAround(lat, lon, radiusKm), list = [];
|
||||
for (var z = 0; z <= MAXZOOM; z++) {
|
||||
var x0 = _x(w, z), x1 = _x(e, z), y0 = _y(n, z), y1 = _y(s, z);
|
||||
var x0 = _x(b.west, z), x1 = _x(b.east, z), y0 = _y(b.north, z), y1 = _y(b.south, z);
|
||||
for (var x = x0; x <= x1; x++) for (var y = y0; y <= y1; y++) list.push([z, x, y]);
|
||||
}
|
||||
return list;
|
||||
|
|
@ -120,11 +123,54 @@ window.MapOffline = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
// POI-Marker der Region mitspeichern (Key-Präfix 'p/<type>' im Tiles-Store) — sonst steht die
|
||||
// Offline-Karte ohne Marker da (Gerätetest 2026-06-06). Quelle: /api/osm/pois (liest die lokale
|
||||
// osm_pois-DB, fast=true). Typen = Werte von OSM_LAYER_MAP in pages/map.js (synchron halten).
|
||||
var POI_TYPES = ['waste_basket', 'dog_park', 'drinking_water', 'tierarzt', 'hundesalon', 'shop',
|
||||
'restaurant', 'bank', 'giftkoeder', 'kotbeutel', 'gefahr', 'parkplatz',
|
||||
'treffpunkt', 'sonstiges', 'hotel'];
|
||||
function _cachePois(bbox) {
|
||||
var total = 0;
|
||||
var jobs = POI_TYPES.map(function (type) {
|
||||
var params = new URLSearchParams({ type: type, fast: 'true',
|
||||
south: bbox.south, west: bbox.west, north: bbox.north, east: bbox.east });
|
||||
return fetch('/api/osm/pois?' + params)
|
||||
.then(function (r) { return r.ok ? r.json() : null; })
|
||||
.then(function (fresh) {
|
||||
if (!fresh || !fresh.length) return;
|
||||
total += fresh.length;
|
||||
// Mit Bestand mergen (per id) — eine zweite Region (Urlaubsort) darf die erste nicht löschen.
|
||||
return _get('p/' + type).then(function (old) {
|
||||
var merged = fresh;
|
||||
if (old && old.length) {
|
||||
var seen = {};
|
||||
fresh.forEach(function (p) { seen[p.id] = true; });
|
||||
merged = fresh.concat(old.filter(function (p) { return !seen[p.id]; }));
|
||||
}
|
||||
return _put('p/' + type, merged);
|
||||
});
|
||||
})
|
||||
.catch(function () {});
|
||||
});
|
||||
return Promise.all(jobs).then(function () { return total; });
|
||||
}
|
||||
|
||||
// Gespeicherte POIs eines Typs im Bbox-Ausschnitt — Offline-Fallback für die Karten-Marker.
|
||||
function pois(type, bbox) {
|
||||
return _get('p/' + type).then(function (list) {
|
||||
if (!list || !list.length) return [];
|
||||
return list.filter(function (p) {
|
||||
return p.lat >= bbox.south && p.lat <= bbox.north && p.lon >= bbox.west && p.lon <= bbox.east;
|
||||
});
|
||||
}).catch(function () { return []; });
|
||||
}
|
||||
|
||||
// Bereich um lat/lon (radiusKm, Default 5) herunterladen + in IndexedDB ablegen.
|
||||
// onProgress({done,total,bytes}). Liefert {tiles,bytes}.
|
||||
// onProgress({done,total,bytes}). Liefert {tiles,bytes,pois}.
|
||||
function downloadAround(lat, lon, radiusKm, onProgress) {
|
||||
radiusKm = radiusKm || 5;
|
||||
var list = _tileList(lat, lon, radiusKm), total = list.length, done = 0, bytes = 0, stored = 0, i = 0, CONC = 6;
|
||||
var poiCount = 0;
|
||||
function next() {
|
||||
if (i >= total) return Promise.resolve();
|
||||
var t = list[i++], key = t[0] + '/' + t[1] + '/' + t[2];
|
||||
|
|
@ -139,10 +185,11 @@ window.MapOffline = (function () {
|
|||
var w = []; for (var k = 0; k < CONC; k++) w.push(next());
|
||||
return Promise.all(w)
|
||||
.then(function () { return _cacheGlyphs(); }) // Glyphs mitcachen (sonst offline kein Render)
|
||||
.then(function (gb) { bytes += gb; return _req(META, 'readwrite', function (os) {
|
||||
os.put({ lat: lat, lon: lon, radiusKm: radiusKm, tiles: stored, bytes: bytes, savedAt: Date.now() }, 'region');
|
||||
.then(function (gb) { bytes += gb; return _cachePois(_bboxAround(lat, lon, radiusKm)); })
|
||||
.then(function (pc) { poiCount = pc; return _req(META, 'readwrite', function (os) {
|
||||
os.put({ lat: lat, lon: lon, radiusKm: radiusKm, tiles: stored, bytes: bytes, pois: poiCount, savedAt: Date.now() }, 'region');
|
||||
}); })
|
||||
.then(function () { return { tiles: stored, bytes: bytes }; });
|
||||
.then(function () { return { tiles: stored, bytes: bytes, pois: poiCount }; });
|
||||
}
|
||||
|
||||
function stats() {
|
||||
|
|
@ -159,6 +206,6 @@ window.MapOffline = (function () {
|
|||
|
||||
return {
|
||||
registerProtocol: registerProtocol, downloadAround: downloadAround, tile: tile, glyph: glyph,
|
||||
stats: stats, hasRegion: hasRegion, clear: clear, MAXZOOM: MAXZOOM,
|
||||
pois: pois, stats: stats, hasRegion: hasRegion, clear: clear, MAXZOOM: MAXZOOM,
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue