100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
import { Airport, AirportCategory } from '@lib/airport.types.ts';
|
|
import { Marker, Popup } from 'react-leaflet';
|
|
import L from 'leaflet';
|
|
import { useRef } from 'react';
|
|
import { getMarkerColor } from '@lib/metar.types.ts';
|
|
import { LayerInfo } from '@/App.tsx';
|
|
|
|
export default function AirportMarker({
|
|
index,
|
|
airport,
|
|
setAirport,
|
|
selectedLayer,
|
|
}: {
|
|
index: number;
|
|
airport: Airport;
|
|
setAirport: (airport: Airport) => void;
|
|
selectedLayer: LayerInfo;
|
|
}) {
|
|
const icon = createCustomIcon(airport, selectedLayer);
|
|
const markerRef = useRef<L.Marker>(null);
|
|
|
|
return (
|
|
<Marker
|
|
key={index}
|
|
ref={markerRef}
|
|
position={[airport.latitude, airport.longitude]}
|
|
icon={icon}
|
|
eventHandlers={{
|
|
click: () => setAirport(airport),
|
|
mouseover: () => markerRef.current?.openPopup(),
|
|
mouseout: () => markerRef.current?.closePopup()
|
|
}}
|
|
>
|
|
<Popup closeButton={false} autoPan={false}>
|
|
{airport.icao} - {airport.name}
|
|
</Popup>
|
|
</Marker>
|
|
);
|
|
}
|
|
|
|
function createCustomIcon(airport: Airport, selectedLayer: LayerInfo): L.DivIcon {
|
|
if (airport.category === AirportCategory.HELIPORT) {
|
|
return L.divIcon({
|
|
html: `
|
|
<div style="
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
border: 2px solid black;
|
|
background-color: ${selectedLayer.markerOutline};
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: {info[1]}">
|
|
<span style="color: black; font-size: 8px; font-weight: bold;">H</span>
|
|
</div>
|
|
`,
|
|
className: '',
|
|
iconSize: [20, 20],
|
|
iconAnchor: [10, 10]
|
|
});
|
|
} else {
|
|
// Default to a filled circle.
|
|
const flightCategory = airport.latest_metar?.flight_category || 'UNKN';
|
|
const color = getMarkerColor(flightCategory);
|
|
if (flightCategory == 'UNKN') {
|
|
return L.divIcon({
|
|
html: `
|
|
<div style="
|
|
background-color: ${color};
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
z-index: {info[1]}">
|
|
</div>
|
|
`,
|
|
className: '',
|
|
iconSize: [20, 20],
|
|
iconAnchor: [10, 10]
|
|
});
|
|
} else {
|
|
return L.divIcon({
|
|
html: `
|
|
<div style="
|
|
background-color: ${color};
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: 50%;
|
|
border: 2px solid ${selectedLayer.markerOutline};
|
|
z-index: {info[1]}">
|
|
</div>
|
|
`,
|
|
className: '',
|
|
iconSize: [20, 20],
|
|
iconAnchor: [10, 10]
|
|
});
|
|
}
|
|
}
|
|
}
|