import { WALKING_ICON } from "/js/icons.js"; import { firstSymbolLayerId } from "/js/radar.js"; const SOURCE_ID = "hiking-trails"; const LAYER_ID = "hiking-trails-line"; // Pre-rendered raster tiles, not vector — waymarkedtrails.org already // colors each route by its OSM `colour` tag (the KST/KČT-style paint-blaze // colors used in Slovakia/Czechia), falling back to plain red where a route // has none, so there's no styling to do here ourselves. Online only, same // "quietly renders nothing without a network" story as the Wikipedia/Radar/ // Contour lines overlays — an offline copy (baked into offline.pmtiles) is // a TODO for once there's a route planner to pair it with, see TODO.adoc. const TILE_URL = "https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png"; const ATTRIBUTION = 'Trails © Waymarked Trails (CC-BY-SA), map data © OpenStreetMap contributors'; const OPACITY = 0.85; // A plain on/off Overlays item, same shape as ContourControl — one static // raster overlay, no scrub/forecast controls to expand into. export class HikingTrailsControl { constructor(map) { this._map = map; this._active = false; // setStyle() (switching Online/Offline) tears down all custom sources/ // layers — put this back if it was on, same as every other Overlays // control. map.on("style.load", () => { if (this._active) this._addLayer(); }); } mount(li) { li.innerHTML = ` `; this._checkbox = li.querySelector(".overlays-panel__toggle"); this._checkbox.addEventListener("change", (event) => this._toggle(event.target.checked)); } _toggle(active) { this._active = active; if (active) this._addLayer(); else this._removeLayer(); } _addLayer() { if (this._map.getSource(SOURCE_ID)) return; this._map.addSource(SOURCE_ID, { type: "raster", tiles: [TILE_URL], tileSize: 256, maxzoom: 17, attribution: ATTRIBUTION, }); // Below labels (same firstSymbolLayerId spot contour.js/radar.js use), // so place names/POI icons stay readable on top of the trail lines. this._map.addLayer( { id: LAYER_ID, type: "raster", source: SOURCE_ID, paint: { "raster-opacity": OPACITY } }, firstSymbolLayerId(this._map), ); } _removeLayer() { if (this._map.getLayer(LAYER_ID)) this._map.removeLayer(LAYER_ID); if (this._map.getSource(SOURCE_ID)) this._map.removeSource(SOURCE_ID); } }