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:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.88.0",
|
"version": "1.89.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -247,6 +247,26 @@
|
|||||||
chart.update('none');
|
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
|
// Mouse-leave on the canvas clears the shared hover state so the map marker
|
||||||
// disappears too.
|
// disappears too.
|
||||||
function onCanvasMouseLeave() {
|
function onCanvasMouseLeave() {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
import WaypointDetailPanel from '$lib/components/hikes/route-builder/WaypointDetailPanel.svelte';
|
import WaypointDetailPanel from '$lib/components/hikes/route-builder/WaypointDetailPanel.svelte';
|
||||||
import ImageDropzone from '$lib/components/hikes/route-builder/ImageDropzone.svelte';
|
import ImageDropzone from '$lib/components/hikes/route-builder/ImageDropzone.svelte';
|
||||||
import RouteStatsBar from '$lib/components/hikes/route-builder/RouteStatsBar.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 { assembleTrackPoints, buildGpx, type GpxImageWaypoint, type GpxTrack } from '$lib/gpx';
|
||||||
|
import type { HikeTrackPoint } from '$types/hikes';
|
||||||
import {
|
import {
|
||||||
builder,
|
builder,
|
||||||
focusWaypoint,
|
focusWaypoint,
|
||||||
@@ -271,6 +273,11 @@
|
|||||||
// chevrons follows the table's numbering.
|
// chevrons follows the table's numbering.
|
||||||
const placedWaypoints = $derived(builder.waypoints.filter((w) => !w.unplaced));
|
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(() => {
|
const focusedIdx = $derived.by(() => {
|
||||||
if (!mapView.focusId) return -1;
|
if (!mapView.focusId) return -1;
|
||||||
return placedWaypoints.findIndex((w) => w.id === mapView.focusId);
|
return placedWaypoints.findIndex((w) => w.id === mapView.focusId);
|
||||||
@@ -477,6 +484,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if elevationTrack.length > 1}
|
||||||
|
<section class="elevation-row" aria-label="Höhenprofil">
|
||||||
|
<ElevationProfile track={elevationTrack} />
|
||||||
|
</section>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<WaypointTable
|
<WaypointTable
|
||||||
{pendingPlacementId}
|
{pendingPlacementId}
|
||||||
onRequestPlacement={startPlacement}
|
onRequestPlacement={startPlacement}
|
||||||
|
|||||||
Reference in New Issue
Block a user