diff --git a/website/src/lib/assets/layers.ts b/website/src/lib/assets/layers.ts index 099402cc1..44b1cf72e 100644 --- a/website/src/lib/assets/layers.ts +++ b/website/src/lib/assets/layers.ts @@ -22,7 +22,7 @@ import { Binoculars, Toilet, } from 'lucide-static'; -import { type StyleSpecification } from 'mapbox-gl'; +import { type RasterDEMSourceSpecification, type StyleSpecification } from 'mapbox-gl'; import ignFrTopo from './custom/ign-fr-topo.json'; import ignFrPlan from './custom/ign-fr-plan.json'; import ignFrSatellite from './custom/ign-fr-satellite.json'; @@ -1453,3 +1453,18 @@ export const overpassQueryData: Record = { symbol: 'Anchor', }, }; + +export const terrainSources: { [key: string]: RasterDEMSourceSpecification } = { + 'mapbox-dem': { + type: 'raster-dem', + url: 'mapbox://mapbox.mapbox-terrain-dem-v1', + tileSize: 512, + maxzoom: 14, + }, + mapterhorn: { + type: 'raster-dem', + url: 'https://tiles.mapterhorn.com/tilejson.json', + }, +}; + +export const defaultTerrainSource = 'mapbox-dem'; diff --git a/website/src/lib/components/map/layer-control/LayerControlSettings.svelte b/website/src/lib/components/map/layer-control/LayerControlSettings.svelte index 27ace9277..5675bae8a 100644 --- a/website/src/lib/components/map/layer-control/LayerControlSettings.svelte +++ b/website/src/lib/components/map/layer-control/LayerControlSettings.svelte @@ -13,6 +13,7 @@ overlays, overlayTree, overpassTree, + terrainSources, } from '$lib/assets/layers'; import { getLayers, isSelected, toggle } from '$lib/components/map/layer-control/utils'; import { i18n } from '$lib/i18n.svelte'; @@ -31,6 +32,7 @@ currentOverpassQueries, customLayers, opacities, + terrainSource, } = settings; const { isLayerFromExtension, getLayerName } = extensionAPI; @@ -233,6 +235,23 @@ + + {i18n._('layers.terrain')} + + + + {i18n._(`layers.label.${$terrainSource}`)} + + + {#each Object.keys(terrainSources) as id} + + {i18n._(`layers.label.${id}`)} + + {/each} + + + + diff --git a/website/src/lib/components/map/map.ts b/website/src/lib/components/map/map.ts index 14e83462a..2983f3f47 100644 --- a/website/src/lib/components/map/map.ts +++ b/website/src/lib/components/map/map.ts @@ -3,8 +3,16 @@ import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder'; import { get, writable, type Writable } from 'svelte/store'; import { settings } from '$lib/logic/settings'; import { tick } from 'svelte'; +import { terrainSources } from '$lib/assets/layers'; -const { treeFileView, elevationProfile, bottomPanelSize, rightPanelSize, distanceUnits } = settings; +const { + treeFileView, + elevationProfile, + bottomPanelSize, + rightPanelSize, + distanceUnits, + terrainSource, +} = settings; let fitBoundsOptions: mapboxgl.MapOptions['fitBoundsOptions'] = { maxZoom: 15, @@ -123,34 +131,14 @@ export class MapboxGLMap { }); map.addControl(scaleControl); map.on('style.load', () => { - map.addSource('mapbox-dem', { - type: 'raster-dem', - url: 'mapbox://mapbox.mapbox-terrain-dem-v1', - tileSize: 512, - maxzoom: 14, - }); - if (map.getPitch() > 0) { - map.setTerrain({ - source: 'mapbox-dem', - exaggeration: 1, - }); - } map.setFog({ color: 'rgb(186, 210, 235)', 'high-color': 'rgb(36, 92, 223)', 'horizon-blend': 0.1, 'space-color': 'rgb(156, 240, 255)', }); - map.on('pitch', () => { - if (map.getPitch() > 0) { - map.setTerrain({ - source: 'mapbox-dem', - exaggeration: 1, - }); - } else { - map.setTerrain(null); - } - }); + map.on('pitch', this.setTerrain.bind(this)); + this.setTerrain(); }); map.on('style.import.load', () => { const basemap = map.getStyle().imports?.find((imprt) => imprt.id === 'basemap'); @@ -162,6 +150,7 @@ export class MapboxGLMap { this._map.set(map); // only set the store after the map has loaded window._map = map; // entry point for extensions this.resize(); + this.setTerrain(); scaleControl.setUnit(get(distanceUnits)); this._onLoadCallbacks.forEach((callback) => callback(map)); @@ -177,6 +166,7 @@ export class MapboxGLMap { scaleControl.setUnit(units); }) ); + this._unsubscribes.push(terrainSource.subscribe(() => this.setTerrain())); } onLoad(callback: (map: mapboxgl.Map) => void) { @@ -217,6 +207,24 @@ export class MapboxGLMap { } } } + + setTerrain() { + const map = get(this._map); + if (map) { + const source = get(terrainSource); + if (!map.getSource(source)) { + map.addSource(source, terrainSources[source]); + } + if (map.getPitch() > 0) { + map.setTerrain({ + source: source, + exaggeration: 1, + }); + } else { + map.setTerrain(null); + } + } + } } export const map = new MapboxGLMap(); diff --git a/website/src/lib/logic/settings.ts b/website/src/lib/logic/settings.ts index f4e6e2cf8..c86df6ac0 100644 --- a/website/src/lib/logic/settings.ts +++ b/website/src/lib/logic/settings.ts @@ -8,6 +8,7 @@ import { defaultOverlayTree, defaultOverpassQueries, defaultOverpassTree, + defaultTerrainSource, type CustomLayer, } from '$lib/assets/layers'; import { browser } from '$app/environment'; @@ -154,6 +155,7 @@ export const settings = { customLayers: new Setting>('customLayers', {}), customBasemapOrder: new Setting('customBasemapOrder', []), customOverlayOrder: new Setting('customOverlayOrder', []), + terrainSource: new Setting('terrainSource', defaultTerrainSource), directionMarkers: new Setting('directionMarkers', false), distanceMarkers: new Setting('distanceMarkers', false), streetViewSource: new Setting('streetViewSource', 'mapillary'), diff --git a/website/src/locales/en.json b/website/src/locales/en.json index f3b65d535..4bf445f04 100644 --- a/website/src/locales/en.json +++ b/website/src/locales/en.json @@ -282,6 +282,7 @@ "update": "Update layer" }, "opacity": "Overlay opacity", + "terrain": "Terrain source", "label": { "basemaps": "Basemaps", "overlays": "Overlays", @@ -379,7 +380,9 @@ "railway-station": "Railway Station", "tram-stop": "Tram Stop", "bus-stop": "Bus Stop", - "ferry": "Ferry" + "ferry": "Ferry", + "mapbox-dem": "Mapbox DEM", + "mapterhorn": "Mapterhorn" } }, "chart": {