From 707e71caf1eac24ecbe7b0c2e29708b007261d84 Mon Sep 17 00:00:00 2001 From: Roman Priesol Date: Wed, 9 Sep 2026 09:33:00 +0200 Subject: [PATCH] Add elevation-tinted terrain (hypsometric color-relief layer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reuses the same raster-dem source the hillshade toggle already added — a color-relief layer tints by elevation band (green valleys through brown mid-slopes to pale grey peaks, in this app's own palette) under the hillshade layer, so one toggle gives the combined shaded-relief look instead of two separate layers. --- TODO.adoc | 2 +- public/js/map.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/TODO.adoc b/TODO.adoc index d277442..35f0bef 100644 --- a/TODO.adoc +++ b/TODO.adoc @@ -26,7 +26,7 @@ independence from connectivity. ** [x] Filter panel as a "Unigrid Matrix" — an icon grid to toggle categories on/off, styled like the legend on an official NPS paper map, instead of plain dropdowns * [ ] Custom vector style (MVT/MapLibre) using the NPS color palette — muted natural tones for forests, water, and contours — so POIs and routes stand out at high zoom ** [ ] Landuse & protections: distinct styling for national parks, nature reserves (translucent green/gray-green), military zones, and private land (important for wild camping) -** [ ] Elevation-tinted terrain (color by height band, not just shading — see the hillshade toggle above) +** [x] Elevation-tinted terrain — a `color-relief` layer (hypsometric tint, this app's own green→brown→gray palette) under the hillshade layer, same "Terrain shading" toggle ** [x] Road hierarchy: clearly distinguish paved roads from unpaved/gravel/track — critical for knowing if the camper can get there == Main menu reorganization (4 modules) diff --git a/public/js/map.js b/public/js/map.js index 4cbe966..f9c05b3 100644 --- a/public/js/map.js +++ b/public/js/map.js @@ -306,6 +306,22 @@ class LayerToggleControl { } const HILLSHADE_ID = "hillshade-dem"; +const COLOR_RELIEF_ID = "elevation-tint"; +// Hypsometric tint reusing this app's own palette (wood_a's green at +// valley floor, the road casing brown through the mid-slopes) rather than +// a generic rainbow ramp, so it reads as part of the same map rather than +// a bolted-on overlay. Stops picked for Central European terrain — the +// Tatras top out around 2600m — not a general-purpose world ramp. +const ELEVATION_COLOR_RAMP = [ + "interpolate", + ["linear"], + ["raster-value"], + 0, "#c3e8ab", + 400, "#dcd08f", + 900, "#c9a66b", + 1600, "#a89a86", + 2600, "#f9f6ef", +]; // Public, unauthenticated, no API key — the same open (SRTM/ArcticDEM-derived) // elevation tiles OpenStreetMap's own hillshade layer and many other free // tools use. Only reachable online; while the offline basemap is active this @@ -363,11 +379,22 @@ class HillshadeControl { attribution: "Terrain tiles: Mapzen, SRTM, ArcticDEM", }; this._map.addSource(HILLSHADE_ID, source); + // Elevation tint under, hillshade on top: the tint sets the base color + // per elevation band, hillshade multiplies slope-shading over it — the + // combined "characteristic relief look" the TODO asked for, not two + // independent layers. + this._map.addLayer({ + id: COLOR_RELIEF_ID, + type: "color-relief", + source: HILLSHADE_ID, + paint: { "color-relief-color": ELEVATION_COLOR_RAMP, "color-relief-opacity": 0.7 }, + }); this._map.addLayer({ id: HILLSHADE_ID, type: "hillshade", source: HILLSHADE_ID, paint: { "hillshade-exaggeration": 0.4 } }); } _removeLayer() { if (this._map.getLayer(HILLSHADE_ID)) this._map.removeLayer(HILLSHADE_ID); + if (this._map.getLayer(COLOR_RELIEF_ID)) this._map.removeLayer(COLOR_RELIEF_ID); if (this._map.getSource(HILLSHADE_ID)) this._map.removeSource(HILLSHADE_ID); } }