Map: default to CyclOSM tiles, add OSM toggle button

This commit is contained in:
Davide Scaini
2026-05-13 23:04:16 +02:00
parent f71162d177
commit 21aea7f225
+54 -6
View File
@@ -21,6 +21,33 @@
{ id: 'trekking', label: 'Hiking' },
];
// ── Tile layers ────────────────────────────────────────────────────────────
const TILES = {
cyclosm: {
tiles: [
'https://a.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
'https://b.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
'https://c.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
],
attribution: '© <a href="https://www.cyclosm.org">CyclOSM</a> | © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
label: 'OSM',
},
osm: {
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
label: 'Cycle',
},
};
let tileLayer = $state('cyclosm');
function toggleTiles() {
tileLayer = tileLayer === 'cyclosm' ? 'osm' : 'cyclosm';
if (!map) return;
const src = map.getSource('base');
if (src) src.setTiles(TILES[tileLayer].tiles);
}
// ── Map init ───────────────────────────────────────────────────────────────
onMount(() => {
map = new maplibregl.Map({
@@ -28,14 +55,14 @@
style: {
version: 8,
sources: {
osm: {
base: {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tiles: TILES.cyclosm.tiles,
tileSize: 256,
attribution: '© OpenStreetMap contributors',
attribution: TILES.cyclosm.attribution,
},
},
layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
layers: [{ id: 'base', type: 'raster', source: 'base' }],
},
center: [12, 42],
zoom: 5,
@@ -242,7 +269,11 @@ ${trkpts}
<!-- Map + elevation -->
<main class="map-area">
<div class="map-wrap" bind:this={mapEl}></div>
<div class="map-wrap" bind:this={mapEl}>
<button class="tile-toggle" onclick={toggleTiles} title="Switch map layer">
{TILES[tileLayer].label}
</button>
</div>
{#if route}
<div class="elevation-wrap">
<ElevationChart {route} />
@@ -360,7 +391,24 @@ ${trkpts}
.small { font-size: 0.75rem; margin: 0; }
.map-area { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.map-wrap { flex: 1; }
.map-wrap { flex: 1; position: relative; }
.tile-toggle {
position: absolute;
top: 0.5rem;
left: 0.5rem;
z-index: 10;
padding: 0.25rem 0.5rem;
border-radius: 0.375rem;
border: 1px solid var(--border);
background: var(--bg-card);
color: var(--text-4);
font-size: 0.7rem;
font-weight: 600;
cursor: pointer;
transition: all 0.15s;
}
.tile-toggle:hover { border-color: var(--accent); color: var(--accent); }
.elevation-wrap { height: 140px; flex-shrink: 0; background: var(--bg-card); border-top: 1px solid var(--border); }
:global(.wp-marker) {