"use client"; import type { Map as MapLibreMap } from "maplibre-gl"; import { type RefObject, useEffect, useState } from "react"; import { cn } from "@/lib/utils"; import { MAP_CONTROL_SURFACE_CLASS_NAME } from "./map-control-styles"; type ScaleLineState = { label: string; width: number; zoom: string; }; type MapScaleLineProps = { mapRef: RefObject; mapReady: boolean; maxWidth?: number; coordinatePrecision?: number; className?: string; }; type CoordinateState = { lng: number; lat: number; }; const DEFAULT_SCALE: ScaleLineState = { label: "500 m", width: 80, zoom: "Z --" }; const MIN_SCALE_WIDTH = 34; const COORDINATE_READOUT_WIDTH_CLASS_NAME = "w-[160px]"; export function MapScaleLine({ mapRef, mapReady, maxWidth = 96, coordinatePrecision = 5, className = "" }: MapScaleLineProps) { const [scale, setScale] = useState(DEFAULT_SCALE); const [coordinate, setCoordinate] = useState(null); const coordinateReadout = coordinate ? createCoordinateReadout(coordinate, coordinatePrecision) : null; const coordinateLabel = coordinateReadout ? `${coordinateReadout.mercatorText} · ${coordinateReadout.lngLatText}` : "移动鼠标读取坐标"; useEffect(() => { const map = mapRef.current; if (!mapReady || !map) { return; } const updateScale = () => { setScale(createScaleLineState(map, maxWidth)); }; updateScale(); map.on("move", updateScale); map.on("zoom", updateScale); map.on("resize", updateScale); return () => { map.off("move", updateScale); map.off("zoom", updateScale); map.off("resize", updateScale); }; }, [mapReady, mapRef, maxWidth]); useEffect(() => { const map = mapRef.current; if (!mapReady || !map) { return; } const handleMove = (event: { lngLat: { lng: number; lat: number } }) => { setCoordinate({ lng: event.lngLat.lng, lat: event.lngLat.lat }); }; const handleLeave = () => { setCoordinate(null); }; map.on("mousemove", handleMove); map.on("mouseout", handleLeave); return () => { map.off("mousemove", handleMove); map.off("mouseout", handleLeave); }; }, [mapReady, mapRef]); return (
{scale.label}
{scale.zoom} EPSG:3857 {coordinateReadout ? ( {coordinateReadout.mercatorText} ) : ( {coordinateLabel} )} Mapbox/OSM
); } function ScaleLineDivider() { return (