feat: Add 'Show points' checkbox to display polyline points

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2025-08-17 18:43:32 +00:00
parent 7b07a8049b
commit f1938509d7

View File

@@ -144,10 +144,11 @@ function MapViewManager({ coords, mapState, setMapState, loading, setSubmenu })
return null; return null;
} }
function PolylineWithArrows({ coords, showDirection }) { function PolylineWithArrows({ coords, showDirection, showPoints }) {
const map = useMap(); const map = useMap();
const polylineRef = useRef(null); const polylineRef = useRef(null);
const decoratorRef = useRef(null); const decoratorRef = useRef(null);
const pointsLayerRef = useRef(null);
useEffect(() => { useEffect(() => {
if (polylineRef.current) { if (polylineRef.current) {
@@ -156,6 +157,9 @@ function PolylineWithArrows({ coords, showDirection }) {
if (decoratorRef.current) { if (decoratorRef.current) {
map.removeLayer(decoratorRef.current); map.removeLayer(decoratorRef.current);
} }
if (pointsLayerRef.current) {
map.removeLayer(pointsLayerRef.current);
}
if (coords && coords.length > 1) { if (coords && coords.length > 1) {
const polyline = leaflet.polyline(coords, { color: 'blue' }); const polyline = leaflet.polyline(coords, { color: 'blue' });
@@ -185,6 +189,21 @@ function PolylineWithArrows({ coords, showDirection }) {
} else { } else {
decoratorRef.current = null; decoratorRef.current = null;
} }
if (showPoints) {
const points = coords.map(coord => leaflet.circleMarker(coord, {
color: 'red',
radius: 3,
weight: 1,
fillColor: 'red',
fillOpacity: 1
}));
const pointsLayer = leaflet.layerGroup(points);
pointsLayerRef.current = pointsLayer;
map.addLayer(pointsLayer);
} else {
pointsLayerRef.current = null;
}
} }
return () => { return () => {
@@ -194,13 +213,16 @@ function PolylineWithArrows({ coords, showDirection }) {
if (decoratorRef.current) { if (decoratorRef.current) {
map.removeLayer(decoratorRef.current); map.removeLayer(decoratorRef.current);
} }
if (pointsLayerRef.current) {
map.removeLayer(pointsLayerRef.current);
}
}; };
}, [coords, map, showDirection]); }, [coords, map, showDirection, showPoints]);
return null; return null;
} }
function Map({data, loading, end, duration, slider, mapState, setMapState, setSubmenu, showDirection, setDrawnItems}) { function Map({data, loading, end, duration, slider, mapState, setMapState, setSubmenu, showDirection, showPoints, setDrawnItems}) {
const range = useMemo(() => parseSlider(end, duration, slider), [end, duration, slider]); const range = useMemo(() => parseSlider(end, duration, slider), [end, duration, slider]);
const coords = useMemo(() => { const coords = useMemo(() => {
@@ -296,7 +318,7 @@ function Map({data, loading, end, duration, slider, mapState, setMapState, setSu
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url='https://maptiles.p.rapidapi.com/en/map/v1/{z}/{x}/{y}.png?rapidapi-key=4375b0b1d8msh0c9e7fa3efb9adfp1769dfjsnd603a0387fea' url='https://maptiles.p.rapidapi.com/en/map/v1/{z}/{x}/{y}.png?rapidapi-key=4375b0b1d8msh0c9e7fa3efb9adfp1769dfjsnd603a0387fea'
/> />
<PolylineWithArrows coords={coords} showDirection={showDirection} /> <PolylineWithArrows coords={coords} showDirection={showDirection} showPoints={showPoints} />
<FeatureGroup> <FeatureGroup>
<EditControl <EditControl
position="topright" position="topright"
@@ -320,7 +342,7 @@ function Map({data, loading, end, duration, slider, mapState, setMapState, setSu
); );
} }
function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, submenu, setSubmenu, showDirection, setShowDirection, setMapState, shareStart, shareEnd, drawnItems}) { function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, submenu, setSubmenu, showDirection, setShowDirection, showPoints, setShowPoints, setMapState, shareStart, shareEnd, drawnItems}) {
const [showRange, setShowRange] = useState(false); const [showRange, setShowRange] = useState(false);
const [isSearching, setIsSearching] = useState(false); const [isSearching, setIsSearching] = useState(false);
const [searchResults, setSearchResults] = useState(null); const [searchResults, setSearchResults] = useState(null);
@@ -805,6 +827,14 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
/> />
Show direction Show direction
</label> </label>
<label className="submenu-checkbox-label">
<input
type="checkbox"
checked={showPoints}
onChange={e => setShowPoints(e.target.checked)}
/>
Show points
</label>
<button onClick={recentreView}>Recentre view</button> <button onClick={recentreView}>Recentre view</button>
<button onClick={excludeArea}>Exclude area</button> <button onClick={excludeArea}>Exclude area</button>
<button onClick={searchArea} disabled={isSearching}> <button onClick={searchArea} disabled={isSearching}>
@@ -858,6 +888,7 @@ function App() {
const initialLng = params.get('lng'); const initialLng = params.get('lng');
const initialZoom = params.get('zoom'); const initialZoom = params.get('zoom');
const initialShowDirection = params.get('showDirection') === 'true'; const initialShowDirection = params.get('showDirection') === 'true';
const initialShowPoints = params.get('showPoints') === 'true';
const shareStartParam = params.get('shareStart'); const shareStartParam = params.get('shareStart');
const shareEndParam = params.get('shareEnd'); const shareEndParam = params.get('shareEnd');
@@ -874,6 +905,7 @@ function App() {
}); });
const [submenu, setSubmenu] = useState(false); const [submenu, setSubmenu] = useState(false);
const [showDirection, setShowDirection] = useState(initialShowDirection); const [showDirection, setShowDirection] = useState(initialShowDirection);
const [showPoints, setShowPoints] = useState(initialShowPoints);
const [drawnItems, setDrawnItems] = useState([]); const [drawnItems, setDrawnItems] = useState([]);
const [data, loading] = useSensor('owntracks', 'OwnTracks', end, duration); const [data, loading] = useSensor('owntracks', 'OwnTracks', end, duration);
@@ -900,6 +932,9 @@ function App() {
if (showDirection) { if (showDirection) {
params.set('showDirection', 'true'); params.set('showDirection', 'true');
} }
if (showPoints) {
params.set('showPoints', 'true');
}
if (mapState.center) { if (mapState.center) {
params.set('lat', mapState.center[0].toFixed(5)); params.set('lat', mapState.center[0].toFixed(5));
params.set('lng', mapState.center[1].toFixed(5)); params.set('lng', mapState.center[1].toFixed(5));
@@ -911,7 +946,7 @@ function App() {
return () => { return () => {
clearTimeout(handler); clearTimeout(handler);
}; };
}, [duration, end, slider, mapState, showDirection]); }, [duration, end, slider, mapState, showDirection, showPoints]);
return ( return (
<div> <div>
@@ -926,6 +961,8 @@ function App() {
setSubmenu={setSubmenu} setSubmenu={setSubmenu}
showDirection={showDirection} showDirection={showDirection}
setShowDirection={setShowDirection} setShowDirection={setShowDirection}
showPoints={showPoints}
setShowPoints={setShowPoints}
setMapState={setMapState} setMapState={setMapState}
shareStart={shareStart} shareStart={shareStart}
shareEnd={shareEnd} shareEnd={shareEnd}
@@ -941,6 +978,7 @@ function App() {
setMapState={setMapState} setMapState={setMapState}
setSubmenu={setSubmenu} setSubmenu={setSubmenu}
showDirection={showDirection} showDirection={showDirection}
showPoints={showPoints}
data={data} data={data}
loading={loading} loading={loading}
setDrawnItems={setDrawnItems} setDrawnItems={setDrawnItems}