From 77da21a41c32d80bdfbf8f8349e9b417893dd2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jovan=20Kruni=C4=87?= Date: Thu, 8 Oct 2026 17:17:26 +0200 Subject: [PATCH] fix: show 3d buildings only when the map is tilted --- .../app/modules/map/map-auto-3d.directive.ts | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/frontend/app/src/app/modules/map/map-auto-3d.directive.ts b/frontend/app/src/app/modules/map/map-auto-3d.directive.ts index b1ae9f50..50dee0bf 100644 --- a/frontend/app/src/app/modules/map/map-auto-3d.directive.ts +++ b/frontend/app/src/app/modules/map/map-auto-3d.directive.ts @@ -1,6 +1,13 @@ import {Directive, HostListener} from '@angular/core'; import {Map, MapMouseEvent, MapStyleDataEvent} from 'maplibre-gl'; +/** Layer ids in the map style */ +const BUILDING_LAYER = 'building'; +const BUILDING_3D_LAYER = 'building-3d'; + +/** + * Switches between flat and 3D buildings depending on whether the map is tilted + */ @Directive({ selector: 'mgl-map[auto-3d]', standalone: true, @@ -16,21 +23,37 @@ export class MapAuto3dDirective { this.updatePitch(event.target); } + /** + * Shows the 3D buildings only while the map is tilted; flat buildings otherwise + */ updatePitch(map: Map) { - if (map.getPitch() === 0) { - const layer = map.getLayer('building-3d'); - if (layer && layer?.visibility !== 'none') { - layer.visibility = 'none'; - map.setPaintProperty('building', 'fill-opacity', 1); - map.setLayerZoomRange('building', 13, 24); - } + if (!map.getLayer(BUILDING_3D_LAYER)) return; + + const flat = map.getPitch() === 0; + + const visibility = flat ? 'none' : 'visible'; + // Nothing to do if the 3D layer is already in the target state. This check matters + // because `pitch` fires on every frame while tilting. `getLayoutProperty` returns + // undefined when the style doesn't set `visibility`; MapLibre then treats the layer as visible. + if ((map.getLayoutProperty(BUILDING_3D_LAYER, 'visibility') ?? 'visible') === visibility) return; + + map.setLayoutProperty(BUILDING_3D_LAYER, 'visibility', visibility); + if (!map.getLayer(BUILDING_LAYER)) return; + if (flat) { + map.setPaintProperty(BUILDING_LAYER, 'fill-opacity', 1); + map.setLayerZoomRange(BUILDING_LAYER, 13, 24); } else { - const layer = map.getLayer('building-3d'); - if (layer && layer?.visibility !== 'visible') { - layer.visibility = 'visible'; - map.setPaintProperty('building', 'fill-opacity', ['interpolate', ['linear'], ['zoom'], 15, 1, 16, 0]); - map.setLayerZoomRange('building', 13, 16); - } + // when tilted, fade the flat buildings out where the 3D ones take over + map.setPaintProperty(BUILDING_LAYER, 'fill-opacity', [ + 'interpolate', + ['linear'], + ['zoom'], + 15, + 1, + 16, + 0, + ]); + map.setLayerZoomRange(BUILDING_LAYER, 13, 16); } } }