From f2ecc1803f3ea294a0c6b7915b61348ed0395b26 Mon Sep 17 00:00:00 2001 From: Marcin Zelent Date: Wed, 16 Nov 2022 15:16:38 +0100 Subject: Remade and extended the app using React --- src/components/Map/Map.tsx | 190 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 src/components/Map/Map.tsx (limited to 'src/components/Map/Map.tsx') diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx new file mode 100644 index 0000000..6f2f469 --- /dev/null +++ b/src/components/Map/Map.tsx @@ -0,0 +1,190 @@ +import { LatLngBounds, Icon, MarkerCluster, DivIcon } from 'leaflet'; +import React, { useMemo, useState } from 'react'; +import ReactDom from 'react-dom/server'; +import { GeoJSON, MapContainer, Marker, TileLayer, ZoomControl, useMap } from 'react-leaflet'; + +import { Group, MediaItem } from '../../models'; +import MarkerClusterGroup from '../../lib/MarkerClusterGroup'; + +import 'leaflet/dist/leaflet.css'; +import styles from './Map.module.css'; +import TileLayerControl, { TileLayerType } from '../TileLayerControl/TileLayerControl'; +import ReactLeafletControl from '../ReactLeafletControl/ReactLeafletControl'; +import { LineString } from 'geojson'; + +interface Props { + group: Group | undefined; + handleMarkerClick: (photo: string) => void; +} + +export default function Map({ group, handleMarkerClick }: Props): JSX.Element { + const [tileLayer, setTileLayer] = useState(TileLayerType.map); + + const displayedMedia = useMemo(() => { + if (group?.media !== undefined) { + return group.media.filter( + (p) => + p.latitude !== undefined && + p.latitude !== null && + !isNaN(p.latitude) && + p.latitude !== 0 && + p.longitude !== undefined && + p.longitude !== null && + !isNaN(p.longitude) && + p.longitude !== 0 && + p.longitude !== 0, + ); + } + + return []; + }, [group]); + + const bounds = useMemo(() => { + if (group === undefined || (group.geoData === undefined && displayedMedia.length === 0)) { + return new LatLngBounds([75, -145], [-52, 145]); + } + + const latitudes = displayedMedia.map((p) => p.latitude) as number[]; + const longitudes = displayedMedia.map((p) => p.longitude) as number[]; + + group.geoData?.forEach((data) => { + if (data.bbox !== undefined) { + latitudes.push(data.bbox[1]); + latitudes.push(data.bbox[3]); + longitudes.push(data.bbox[0]); + longitudes.push(data.bbox[2]); + } + }); + + const minLatitude = Math.min(...latitudes); + const minLongitude = Math.min(...longitudes); + const maxLatitude = Math.max(...latitudes); + const maxLongitude = Math.max(...longitudes); + + return new LatLngBounds([minLatitude, minLongitude], [maxLatitude, maxLongitude]); + }, [group]); + + function getClusterGroupIcon(markerCluster: MarkerCluster): DivIcon { + const iconUrl = markerCluster + .getAllChildMarkers() + .filter((m) => m.getIcon().options.iconUrl !== '/icons/thumb-placeholder.png')[0] + .getIcon().options.iconUrl; + + return new DivIcon({ + html: ReactDom.renderToString( + <> + + {markerCluster.getChildCount()} + , + ), + iconSize: [36, 36], + className: styles.markerIcon, + }); + } + + function createMarkers(media: MediaItem[]): JSX.Element { + if (media.length === 0) { + return <>; + } + + return ( + + {media.map((mediaItem, index) => ( + handleMarkerClick(mediaItem.name) }} + /> + ))} + + ); + } + + const mapBounds = useMemo(() => { + function MapBounds({ bounds }: { bounds: LatLngBounds }): JSX.Element { + const map = useMap(); + + if (map !== undefined) { + map.setView(bounds.getCenter()); + map.fitBounds(bounds, { padding: [40, 40] }); + } + + return <>; + } + + return ; + }, [group]); + + return ( + + <> + + + setTileLayer( + tileLayer === TileLayerType.map ? TileLayerType.satellite : TileLayerType.map, + ) + } + /> + + {tileLayer === TileLayerType.map ? ( + + ) : ( + + )} + + {mapBounds} + {createMarkers(displayedMedia)} + {group?.geoData?.map((data, i) => { + const coordinates = (data.features?.[0]?.geometry as LineString).coordinates; + const startCoords = coordinates[0].slice(0, 2).reverse(); + const finishCoords = coordinates[coordinates.length - 1].slice(0, 2).reverse(); + + return ( + + + + + + ); + })} + + + ); +} -- cgit v1.2.3