fix: switchMapStyle loads style as JSON with absolute tile URLs
Fixes trails/tracks not rendering after theme switch. The issue was that map.setStyle(url) caused MapLibre to resolve relative tile paths without /enduro/ prefix, resulting in 404s.
This commit is contained in:
@@ -88,6 +88,7 @@ function switchMapStyle() {
|
||||
if (!map) return;
|
||||
const dark = isDarkTheme();
|
||||
const basePath = window.location.pathname.replace(/\/[^/]*$/, '') || '';
|
||||
const tileBase = window.location.origin + basePath;
|
||||
const styleUrl = dark ? basePath + '/style-dark.json' : basePath + '/style.json';
|
||||
|
||||
// Save current position before style change
|
||||
@@ -96,19 +97,22 @@ function switchMapStyle() {
|
||||
const bearing = map.getBearing();
|
||||
const pitch = map.getPitch();
|
||||
|
||||
fetch(styleUrl, { method: 'HEAD' }).then(r => {
|
||||
if (r.ok) {
|
||||
map.setStyle(styleUrl);
|
||||
// Restore position and overlays after style loads
|
||||
map.once('idle', () => {
|
||||
map.jumpTo({ center, zoom, bearing, pitch });
|
||||
rebuildMapOverlays();
|
||||
});
|
||||
} else {
|
||||
console.log('Map style not available:', styleUrl);
|
||||
fetch(styleUrl).then(r => {
|
||||
if (r.ok) return r.json();
|
||||
throw new Error('Style not available');
|
||||
}).then(style => {
|
||||
// Fix tile URLs to absolute (same as initMap)
|
||||
if (style.sources && style.sources['trails-tiles'] && style.sources['trails-tiles'].tiles) {
|
||||
style.sources['trails-tiles'].tiles = [`${tileBase}/api/tiles/{z}/{x}/{y}.mvt`];
|
||||
}
|
||||
map.setStyle(style);
|
||||
// Restore position and overlays after style loads
|
||||
map.once('idle', () => {
|
||||
map.jumpTo({ center, zoom, bearing, pitch });
|
||||
rebuildMapOverlays();
|
||||
});
|
||||
}).catch(() => {
|
||||
// Network error, don't switch
|
||||
// Network error or style not available, don't switch
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1436,52 +1440,9 @@ async function initMap() {
|
||||
zoomEl.textContent = 'z' + zoom;
|
||||
}
|
||||
|
||||
// ─── Scale bar & Zoom level ───────────────────────────────────────────────
|
||||
|
||||
function updateScaleBar() {
|
||||
const zoom = map.getZoom();
|
||||
const lat = map.getCenter().lat;
|
||||
// Метров на пиксель при текущем зуме и широте
|
||||
const metersPerPixel = 156543.03392 * Math.cos(lat * Math.PI / 180) / Math.pow(2, zoom);
|
||||
// Целевая ширина линейки ~100px
|
||||
const targetWidth = 100;
|
||||
const meters = metersPerPixel * targetWidth;
|
||||
|
||||
let label, width;
|
||||
if (meters >= 1000) {
|
||||
const km = Math.round(meters / 1000);
|
||||
label = km + ' км';
|
||||
width = km * 1000 / metersPerPixel;
|
||||
} else {
|
||||
const m = Math.round(meters / 50) * 50 || 50;
|
||||
label = m + ' м';
|
||||
width = m / metersPerPixel;
|
||||
}
|
||||
|
||||
const scaleLine = document.getElementById('scale-line');
|
||||
const scaleLabel = document.getElementById('scale-label');
|
||||
if (scaleLine) scaleLine.style.width = Math.round(width) + 'px';
|
||||
if (scaleLabel) scaleLabel.textContent = label;
|
||||
}
|
||||
|
||||
function updateZoomLevel() {
|
||||
const el = document.getElementById('zoom-level');
|
||||
if (el) el.textContent = Math.round(map.getZoom());
|
||||
}
|
||||
|
||||
updateScaleZoom();
|
||||
updateScaleBar();
|
||||
updateZoomLevel();
|
||||
map.on('zoom', () => {
|
||||
updateScaleZoom();
|
||||
updateScaleBar();
|
||||
updateZoomLevel();
|
||||
if (typeof updateHillshadeAvailability === 'function') updateHillshadeAvailability();
|
||||
});
|
||||
map.on('move', () => {
|
||||
updateScaleZoom();
|
||||
updateScaleBar();
|
||||
});
|
||||
map.on('zoom', updateScaleZoom);
|
||||
map.on('move', updateScaleZoom);
|
||||
|
||||
map.on('load', () => {
|
||||
checkDataAvailability();
|
||||
|
||||
Reference in New Issue
Block a user