"use client"; import React, { useCallback, useEffect, useState } from "react"; import { useAtomValue } from "jotai"; import { mapAtom } from "../../state/map"; const ScaleBar: React.FC = () => { const map = useAtomValue(mapAtom); const [barWidth, setBarWidth] = useState(0); const [label, setLabel] = useState(""); const [barStyle, setBarStyle] = useState({}); useEffect(() => { setBarStyle({ width: barWidth + "px", left: 5 + (125 - barWidth) / 2 + "px", height: "2px", }); }, [barWidth]); const getRoundNumMeter = (meters: number): number => { const roundNumbers = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000]; for (const num of roundNumbers) { if (meters <= num) return num; } return 1000000; }; const updateScaleBar = useCallback(() => { if (!map) return; const halfHeight = map.getSize().y / 2; const maxPixelWidth = 100; const maxMeters = map.containerPointToLatLng([0, halfHeight]).distanceTo(map.containerPointToLatLng([maxPixelWidth, halfHeight])); const meters = getRoundNumMeter(maxMeters); const label = meters < 1000 ? `${meters} m` : `${meters / 1000} km`; setBarWidth((meters / maxMeters) * maxPixelWidth); setLabel(label); }, [map]); useEffect(() => { if (map) { updateScaleBar(); map.on("zoomend", updateScaleBar); map.on("moveend", updateScaleBar); return () => { map.off("zoomend", updateScaleBar); map.off("moveend", updateScaleBar); }; } }, [map, updateScaleBar]); return (
); }; export default ScaleBar;