diff --git a/static/css/adsb_dashboard.css b/static/css/adsb_dashboard.css index f343550..955b63f 100644 --- a/static/css/adsb_dashboard.css +++ b/static/css/adsb_dashboard.css @@ -862,6 +862,9 @@ body { min-height: 300px; min-width: 0; overflow: hidden; + background: #08121c; + contain: layout paint; + overflow-anchor: none; } @media (min-width: 768px) { @@ -880,17 +883,19 @@ body { .display-container { position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; + inset: 0; + isolation: isolate; + contain: layout paint; + overflow-anchor: none; } #radarMap { - position: relative; - width: 100%; - height: 100%; + position: absolute; + inset: 0; display: block; + background: #08121c; + contain: layout paint; + overflow-anchor: none; } .map-crosshair-overlay { @@ -904,6 +909,16 @@ body { --crosshair-x-end: 50%; --crosshair-y-end: 50%; --crosshair-duration: 1500ms; + contain: layout paint; + overflow-anchor: none; +} + +#radarMap .leaflet-pane, +#radarMap .leaflet-map-pane, +#radarMap .leaflet-tile-pane, +#radarMap .leaflet-overlay-pane, +#radarMap .leaflet-tile { + overflow-anchor: none; } .map-crosshair-line { diff --git a/templates/adsb_dashboard.html b/templates/adsb_dashboard.html index f199adc..d793265 100644 --- a/templates/adsb_dashboard.html +++ b/templates/adsb_dashboard.html @@ -453,6 +453,8 @@ let panelSelectionFallbackTimer = null; let panelSelectionStageTimer = null; let mapCrosshairRequestId = 0; + let radarMapResizeObserver = null; + let radarMapSizeSyncFrame = null; // Watchlist - persisted to localStorage let watchlist = JSON.parse(localStorage.getItem('adsb_watchlist') || '[]'); @@ -1730,6 +1732,14 @@ ACARS: ${r.statistics.acarsMessages} messages`; window.addEventListener('pagehide', function() { if (eventSource) { eventSource.close(); eventSource = null; } if (gpsEventSource) { gpsEventSource.close(); gpsEventSource = null; } + if (radarMapResizeObserver) { + radarMapResizeObserver.disconnect(); + radarMapResizeObserver = null; + } + if (radarMapSizeSyncFrame) { + cancelAnimationFrame(radarMapSizeSyncFrame); + radarMapSizeSyncFrame = null; + } }); document.addEventListener('DOMContentLoaded', () => { @@ -2134,6 +2144,29 @@ sudo make install return layer; } + function scheduleRadarMapSizeSync(drawRings = false) { + if (!radarMap) return; + if (radarMapSizeSyncFrame) { + cancelAnimationFrame(radarMapSizeSyncFrame); + } + radarMapSizeSyncFrame = requestAnimationFrame(() => { + radarMapSizeSyncFrame = null; + if (!radarMap) return; + radarMap.invalidateSize({ pan: false, debounceMoveend: true }); + if (drawRings) { + drawRangeRings(); + } + }); + } + + function attachRadarMapResizeObserver(container) { + if (!container || radarMapResizeObserver || typeof ResizeObserver === 'undefined') return; + radarMapResizeObserver = new ResizeObserver(() => { + scheduleRadarMapSizeSync(true); + }); + radarMapResizeObserver.observe(container); + } + async function initMap() { // Guard against double initialization (e.g. bfcache restore) const container = document.getElementById('radarMap'); @@ -2153,18 +2186,10 @@ sudo make install // when internet map providers are slow or unreachable. const fallbackTiles = createFallbackGridLayer().addTo(radarMap); - // Draw range rings after map is ready - setTimeout(() => drawRangeRings(), 100); - - // Fix map size on mobile after initialization - setTimeout(() => { - if (radarMap) radarMap.invalidateSize(); - }, 200); - - // Additional invalidateSize to ensure all tiles load - setTimeout(() => { - if (radarMap) radarMap.invalidateSize(); - }, 500); + radarMap.whenReady(() => { + scheduleRadarMapSizeSync(true); + }); + attachRadarMapResizeObserver(container); // Upgrade tiles via Settings in the background (non-blocking) if (typeof Settings !== 'undefined') { @@ -2184,14 +2209,12 @@ sudo make install // Handle window resize for map (especially important on mobile) window.addEventListener('resize', function() { - if (radarMap) radarMap.invalidateSize(); + scheduleRadarMapSizeSync(true); }); // Handle orientation changes for mobile devices window.addEventListener('orientationchange', function() { - setTimeout(() => { - if (radarMap) radarMap.invalidateSize(); - }, 200); + scheduleRadarMapSizeSync(true); }); // ============================================