diff --git a/mapper/src/App.js b/mapper/src/App.js index 251a364..e44395d 100644 --- a/mapper/src/App.js +++ b/mapper/src/App.js @@ -222,44 +222,7 @@ function PolylineWithArrows({ coords, showDirection, showPoints }) { return null; } -function Map({data, loading, end, duration, slider, mapState, setMapState, setSubmenu, showDirection, showPoints, setDrawnItems}) { - const range = useMemo(() => parseSlider(end, duration, slider), [end, duration, slider]); - - const coords = useMemo(() => { - // 1. Guard against invalid top-level data - if (!Array.isArray(data)) { - return []; - } - - const result = []; - const [startTime, endTime] = range; - - // 2. Loop through the data - for (const point of data) { - // 3. Guard against malformed points - if (!point || typeof point !== 'object') { - continue; - } - - const { lat, lon, time } = point; - - // 4. Guard against invalid time - if (typeof time !== 'string' || time.length === 0) { - continue; - } - - // 5. Guard against invalid coordinates (null, undefined, NaN, non-number) - if (typeof lat !== 'number' || typeof lon !== 'number' || !isFinite(lat) || !isFinite(lon)) { - continue; - } - - // 6. Now that all data is known to be valid, filter by time - if (time >= startTime && time <= endTime) { - result.push([lat, lon]); - } - } - return result; - }, [data, range]); +function Map({data, loading, coords, mapState, setMapState, setSubmenu, showDirection, showPoints, setDrawnItems}) { const handleSubmit = (e) => { e.preventDefault(); @@ -342,7 +305,7 @@ function Map({data, loading, end, duration, slider, mapState, setMapState, setSu ); } -function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, submenu, setSubmenu, showDirection, setShowDirection, showPoints, setShowPoints, setMapState, shareStart, shareEnd, drawnItems}) { +function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, submenu, setSubmenu, showDirection, setShowDirection, showPoints, setShowPoints, setMapState, shareStart, shareEnd, drawnItems, coords}) { const [showRange, setShowRange] = useState(false); const [isSearching, setIsSearching] = useState(false); const [searchResults, setSearchResults] = useState(null); @@ -648,6 +611,25 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm setSearchResults(newResults); }; + const totalDistance = useMemo(() => { + if (!coords || coords.length < 2) { + return null; + } + + let distance = 0; + for (let i = 0; i < coords.length - 1; i++) { + const p1 = leaflet.latLng(coords[i]); + const p2 = leaflet.latLng(coords[i+1]); + distance += p1.distanceTo(p2); + } + + if (distance < 1000) { + return `${distance.toFixed(0)} m`; + } else { + return `${(distance / 1000).toFixed(2)} km`; + } + }, [coords]); + const range = parseSlider(end, duration, slider); const startDate = moment(end).subtract(...duration.delta); @@ -739,7 +721,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm return (
{(showRange || !!submenu) &&
- {rangeTime(range[0])} - {rangeTime(range[1])} ({rangeDelta(range)}) + {rangeTime(range[0])} - {rangeTime(range[1])} ({rangeDelta(range)}){totalDistance && ({totalDistance})}
}
@@ -968,6 +950,44 @@ function App() { const [data, loading] = useSensor('owntracks', 'OwnTracks', end, duration); + const range = useMemo(() => parseSlider(end, duration, slider), [end, duration, slider]); + + const coords = useMemo(() => { + // 1. Guard against invalid top-level data + if (!Array.isArray(data)) { + return []; + } + + const result = []; + const [startTime, endTime] = range; + + // 2. Loop through the data + for (const point of data) { + // 3. Guard against malformed points + if (!point || typeof point !== 'object') { + continue; + } + + const { lat, lon, time } = point; + + // 4. Guard against invalid time + if (typeof time !== 'string' || time.length === 0) { + continue; + } + + // 5. Guard against invalid coordinates (null, undefined, NaN, non-number) + if (typeof lat !== 'number' || typeof lon !== 'number' || !isFinite(lat) || !isFinite(lon)) { + continue; + } + + // 6. Now that all data is known to be valid, filter by time + if (time >= startTime && time <= endTime) { + result.push([lat, lon]); + } + } + return result; + }, [data, range]); + const shareStart = shareStartParam ? moment.unix(shareStartParam) : null; const shareEnd = shareEndParam ? moment.unix(shareEndParam) : null; @@ -1026,12 +1046,10 @@ function App() { shareEnd={shareEnd} data={data} drawnItems={drawnItems} + coords={coords} />
);