feat(route-builder): show live elevation profile under the map

Render ElevationProfile below the route-builder map, fed by the routed segments (elevations fill in as the swisstopo enrichment resolves). Add a $effect in ElevationProfile so its dataset rebuilds when the track changes live during editing.
This commit is contained in:
2026-05-25 14:51:32 +02:00
parent a4c2efe4f3
commit 8459327717
3 changed files with 34 additions and 1 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "homepage",
"version": "1.88.0",
"version": "1.89.0",
"private": true,
"type": "module",
"scripts": {
@@ -247,6 +247,26 @@
chart.update('none');
});
// Rebuild the dataset when the track data itself changes — e.g. the route
// builder edits the route live. On the static detail page `track` is stable
// after its one-time fetch, so this runs once (no-op) and never again.
$effect(() => {
const pts = track;
const ck = cumKm;
if (!chart) return;
chart.data.datasets[0].data = pts.map((p, i) => ({
x: ck[i],
y: typeof p[2] === 'number' ? p[2] : null
}));
const b = xBounds();
const xScale = chart.options.scales?.x;
if (xScale) {
xScale.min = b.min;
xScale.max = b.max;
}
chart.update('none');
});
// Mouse-leave on the canvas clears the shared hover state so the map marker
// disappears too.
function onCanvasMouseLeave() {
@@ -6,7 +6,9 @@
import WaypointDetailPanel from '$lib/components/hikes/route-builder/WaypointDetailPanel.svelte';
import ImageDropzone from '$lib/components/hikes/route-builder/ImageDropzone.svelte';
import RouteStatsBar from '$lib/components/hikes/route-builder/RouteStatsBar.svelte';
import ElevationProfile from '$lib/components/hikes/ElevationProfile.svelte';
import { assembleTrackPoints, buildGpx, type GpxImageWaypoint, type GpxTrack } from '$lib/gpx';
import type { HikeTrackPoint } from '$types/hikes';
import {
builder,
focusWaypoint,
@@ -271,6 +273,11 @@
// chevrons follows the table's numbering.
const placedWaypoints = $derived(builder.waypoints.filter((w) => !w.unplaced));
// Flatten the routed segments ([lng, lat, ele?]) into one track for the
// elevation profile below the map. Elevations fill in once the Swisstopo
// enrichment resolves; until then those points read as gaps in the chart.
const elevationTrack = $derived(builder.routedSegments.flat() as HikeTrackPoint[]);
const focusedIdx = $derived.by(() => {
if (!mapView.focusId) return -1;
return placedWaypoints.findIndex((w) => w.id === mapView.focusId);
@@ -477,6 +484,12 @@
</div>
</div>
{#if elevationTrack.length > 1}
<section class="elevation-row" aria-label="Höhenprofil">
<ElevationProfile track={elevationTrack} />
</section>
{/if}
<WaypointTable
{pendingPlacementId}
onRequestPlacement={startPlacement}