feat: add settings modal for map display
This commit is contained in:
@@ -5,14 +5,20 @@ import {
|
||||
Marker,
|
||||
Popup,
|
||||
TileLayer,
|
||||
Tooltip,
|
||||
useMap,
|
||||
useMapEvents,
|
||||
} from 'react-leaflet';
|
||||
import type { MapTileStyle } from './mapStyles';
|
||||
import type { BBox, ParsedOsmResult } from '../search/types';
|
||||
|
||||
type MapViewProps = {
|
||||
results: ParsedOsmResult[];
|
||||
selectedResultId: string | null;
|
||||
tileStyle: MapTileStyle;
|
||||
showResultLabels: boolean;
|
||||
fitMapToResults: boolean;
|
||||
dimMap: boolean;
|
||||
onResultSelect: (id: string) => void;
|
||||
onViewportChange: (bbox: BBox) => void;
|
||||
};
|
||||
@@ -23,6 +29,10 @@ const DEFAULT_ZOOM = 13;
|
||||
export function MapView({
|
||||
results,
|
||||
selectedResultId,
|
||||
tileStyle,
|
||||
showResultLabels,
|
||||
fitMapToResults,
|
||||
dimMap,
|
||||
onResultSelect,
|
||||
onViewportChange,
|
||||
}: MapViewProps) {
|
||||
@@ -53,14 +63,17 @@ export function MapView({
|
||||
center={DEFAULT_CENTER}
|
||||
zoom={DEFAULT_ZOOM}
|
||||
minZoom={3}
|
||||
className="map-view"
|
||||
className={dimMap ? 'map-view map-view-dimmed' : 'map-view'}
|
||||
zoomControl
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
key={tileStyle.id}
|
||||
attribution={tileStyle.attribution}
|
||||
url={tileStyle.url}
|
||||
maxZoom={tileStyle.maxZoom}
|
||||
/>
|
||||
<ViewportReporter onViewportChange={onViewportChange} />
|
||||
<FitResults results={results} enabled={fitMapToResults} />
|
||||
<SelectedResultFocus result={results.find((item) => item.id === selectedResultId) ?? null} />
|
||||
{results.map((result) => (
|
||||
<Marker
|
||||
@@ -76,6 +89,11 @@ export function MapView({
|
||||
<br />
|
||||
{result.type} {result.osmId}
|
||||
</Popup>
|
||||
{showResultLabels ? (
|
||||
<Tooltip permanent direction="top" offset={[0, -10]} opacity={0.94}>
|
||||
{result.name ?? `${result.type} ${result.osmId}`}
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
@@ -99,6 +117,33 @@ function ViewportReporter({
|
||||
return null;
|
||||
}
|
||||
|
||||
function FitResults({
|
||||
results,
|
||||
enabled,
|
||||
}: {
|
||||
results: ParsedOsmResult[];
|
||||
enabled: boolean;
|
||||
}) {
|
||||
const map = useMap();
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled || results.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bounds = L.latLngBounds(results.map((result) => [result.lat, result.lon]));
|
||||
|
||||
if (bounds.isValid()) {
|
||||
map.fitBounds(bounds.pad(0.2), {
|
||||
animate: true,
|
||||
maxZoom: 16,
|
||||
});
|
||||
}
|
||||
}, [enabled, map, results]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function SelectedResultFocus({ result }: { result: ParsedOsmResult | null }) {
|
||||
const map = useMap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user