From 3e3c3ee821faf1947930586ce45a6342ceb6f9c5 Mon Sep 17 00:00:00 2001 From: Franzz Date: Wed, 29 Jul 2026 00:04:20 +0200 Subject: [PATCH] Map terrain --- resources/lang/en.json | 1 + resources/lang/es.json | 1 + resources/lang/fr.json | 1 + src/components/project.vue | 52 ++++++++++++++++++++++++++++++ src/components/projectSettings.vue | 15 ++++++++- 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index 1d6b539..6220f23 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -64,6 +64,7 @@ "outdoors": "Mapbox Outdoors", "satellite": "Satellite", "see_on_google": "View position on Google Maps", + "terrain": "3D terrain", "title": "Base maps", "usgs": "USGS" }, diff --git a/resources/lang/es.json b/resources/lang/es.json index 64691f5..d21f81c 100644 --- a/resources/lang/es.json +++ b/resources/lang/es.json @@ -64,6 +64,7 @@ "outdoors": "Mapbox Topo", "satellite": "Satélite", "see_on_google": "Ver la posición en Google Maps", + "terrain": "Relieve 3D", "title": "Mapas de base", "usgs": "USGS" }, diff --git a/resources/lang/fr.json b/resources/lang/fr.json index f5d7b3d..7bbdda6 100644 --- a/resources/lang/fr.json +++ b/resources/lang/fr.json @@ -64,6 +64,7 @@ "outdoors": "Mapbox Topo", "satellite": "Satellite", "see_on_google": "Voir la position sur Google Maps", + "terrain": "Relief 3D", "title": "Fonds de carte", "usgs": "USGS" }, diff --git a/src/components/project.vue b/src/components/project.vue index 86f24d9..53423ba 100644 --- a/src/components/project.vue +++ b/src/components/project.vue @@ -63,6 +63,7 @@ export default { modeHisto: null, baseMaps: [], baseMap: null, + terrainEnabled: false, map: null, mapInitializing: false, markerHeight: 32, //FIXME @@ -96,6 +97,11 @@ export default { if(sNewBaseMap && this.map.getLayer(sNewBaseMap)) this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible'); } }, + terrainEnabled(bEnabled) { + if(!this.map?.isStyleLoaded()) return; + if(bEnabled) this.addTerrain(); + else this.removeTerrain(); + }, 'hash.items.0'(newProjectCodename, oldProjectCodename) { //hash.items.0 = Project Code Name if(newProjectCodename != oldProjectCodename) { this.hash.items = [newProjectCodename]; //Force removal of direct link @@ -264,6 +270,7 @@ export default { }, addMapContent() { this.baseMaps.forEach(this.addBaseMap); + if(this.terrainEnabled) this.addTerrain(); this.addTrack(); this.markers.forEach(this.addMarker); }, @@ -273,8 +280,52 @@ export default { this.closePopup(); this.removeTrack(); this.markers.forEach(this.removeMarker); + this.removeTerrain(); this.baseMaps.forEach(this.removeBaseMap); }, + addTerrain() { + // MapLibre terrain's fog matrix is only implemented for Mercator. + this.map.setProjection({type: 'mercator'}); + if(!this.map.getSource('terrain-dem')) { + this.map.addSource('terrain-dem', { + type: 'raster-dem', + tiles: ['https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png'], + tileSize: 256, + maxzoom: 15, + encoding: 'terrarium' + }); + } + if(!this.map.getSource('hillshade-dem')) { + this.map.addSource('hillshade-dem', { + type: 'raster-dem', + tiles: ['https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png'], + tileSize: 256, + maxzoom: 13, + encoding: 'terrarium' + }); + } + if(!this.map.getLayer('terrain-hillshade')) { + this.map.addLayer({ + id: 'terrain-hillshade', + type: 'hillshade', + source: 'hillshade-dem', + paint: { + 'hillshade-exaggeration': 0.35, + 'hillshade-shadow-color': '#2d342b', + 'hillshade-highlight-color': '#ffffff' + } + }); + } + this.map.setTerrain({source: 'terrain-dem', exaggeration: 1.25}); + }, + removeTerrain() { + if(!this.map) return; + if(this.map.getTerrain()) this.map.setTerrain(null); + if(this.map.getLayer('terrain-hillshade')) this.map.removeLayer('terrain-hillshade'); + if(this.map.getSource('hillshade-dem')) this.map.removeSource('hillshade-dem'); + if(this.map.getSource('terrain-dem')) this.map.removeSource('terrain-dem'); + this.map.setProjection({type: 'globe'}); + }, addBaseMap(asBaseMap) { if(asBaseMap.default_map) this.baseMap = asBaseMap.codename; if(this.map.getSource(asBaseMap.codename) && this.map.getLayer(asBaseMap.codename)) return; @@ -642,6 +693,7 @@ export default { v-model:project-code-name="hash.items[0]" :base-maps="baseMaps" v-model:base-map="baseMap" + v-model:terrain-enabled="terrainEnabled" :map-initializing="mapInitializing" :hikes="hikes" @toggle="(bIsOpen, iAnimDuration) => onPanelToggle('left', bIsOpen, iAnimDuration)" diff --git a/src/components/projectSettings.vue b/src/components/projectSettings.vue index 57cf70b..7b8ba26 100644 --- a/src/components/projectSettings.vue +++ b/src/components/projectSettings.vue @@ -17,6 +17,7 @@ export default { projectCodeName: String, baseMaps: Array, baseMap: String, + terrainEnabled: Boolean, mapInitializing: Boolean, hikes: Object }, @@ -28,7 +29,7 @@ export default { logoTitleUrl }; }, - emits: ['update:baseMap', 'update:projectCodeName', 'toggle'], + emits: ['update:baseMap', 'update:projectCodeName', 'update:terrainEnabled', 'toggle'], inject: ['api', 'lang', 'user', 'consts', 'isMobile', 'hash'], computed: { project() { @@ -49,6 +50,14 @@ export default { set(sBaseMap) { this.$emit('update:baseMap', sBaseMap); } + }, + terrainEnabledModel: { + get() { + return this.terrainEnabled; + }, + set(bTerrainEnabled) { + this.$emit('update:terrainEnabled', bTerrainEnabled); + } } }, watch: { @@ -110,6 +119,10 @@ export default { +
+ + +