From 4b0070473592b3a72dfb318f1e19f682f9ec178e Mon Sep 17 00:00:00 2001 From: hermes-explorigin Date: Sun, 9 Aug 2026 15:31:59 +0000 Subject: [PATCH] Directions: smart distance units (m/km auto + toggle) and travel-time estimate - DirectionsPanel: unit selector (Auto = m under 1km else km, or force m/km) and a Drive/Walk mode that estimates travel time from distance + avg speed - Distance shows meters for short routes and km for longer ones; est. time in seconds/minutes/hours as appropriate - README: document the new units and travel-time options --- README.md | 6 +- src/lib/components/DirectionsPanel.svelte | 74 +++++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fa9431c..695c380 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,11 @@ button appears in the top bar. Opening it lets you: - **Set start (A)** and **end (B)** by clicking the map. - **Avoid certain POI categories** along the route (schools, fire stations, fuel stations, parking, restaurants, …). -- **Compute** a route and **draw it** on the map, with total driving distance. +- **Compute** a route and **draw it** on the map. +- Choose **distance units** (`m` / `km`, or `Auto` — meters under 1 km, + kilometers otherwise) and a **travel mode** (Drive or Walk). +- See the route's **distance** and an **estimated travel time** (computed from + the mode's average speed). Routing is done **entirely in the browser** (`src/lib/routing.ts`): an A*-search over the graph built from the OSM dump. Point A/B are snapped to the diff --git a/src/lib/components/DirectionsPanel.svelte b/src/lib/components/DirectionsPanel.svelte index 276f0b6..6a7ddb0 100644 --- a/src/lib/components/DirectionsPanel.svelte +++ b/src/lib/components/DirectionsPanel.svelte @@ -18,10 +18,16 @@ let from = $state<[number, number] | null>(null); let to = $state<[number, number] | null>(null); - let result = $state(null); + let result = $state(null); let computing = $state(false); let picking: 'from' | 'to' | null = $state(null); + // Units for distance output: 'auto' (m if < 1km else km), 'm', or 'km'. + let unit = $state<'auto' | 'm' | 'km'>('auto'); + // Travel-time mode: average speed (km/h) used for the estimate. + let mode = $state<'drive' | 'walk'>('drive'); + const SPEEDS = { drive: 45, walk: 4.8 }; // km/h + let routeLayer: L.LayerGroup | null = null; const CATEGORIES = [ @@ -34,6 +40,29 @@ ]; const selected = $state>({}); + // Format distance in meters/km according to the selected unit. + function formatDistance(m: number): string { + if (unit === 'm' || (unit === 'auto' && m < 1000)) { + const v = m < 10 ? m.toFixed(1) : Math.round(m).toString(); + return `${v} m`; + } + // km + const km = m / 1000; + const v = km < 10 ? km.toFixed(2) : km.toFixed(1); + return `${v} km`; + } + + // Estimate travel time (minutes) from distance + mode speed. + function formatTime(m: number): string { + const speedKmh = SPEEDS[mode]; + const minutes = m / 1000 / speedKmh * 60; + if (minutes < 1) return `${Math.max(1, Math.round(minutes * 60))}s`; + if (minutes < 60) return `${Math.round(minutes)} min`; + const h = Math.floor(minutes / 60); + const min = Math.round(minutes % 60); + return min ? `${h} h ${min} min` : `${h} h`; + } + async function loadData() { if (loadingData || graph) return; loadingData = true; @@ -145,6 +174,24 @@ {/each} +
+
+ + +
+
+ + +
+
+ {#if from && to} {:else} @@ -168,7 +225,7 @@