import { Button, Col, Form, Input, Modal, Row, Select, Spin } from "antd"; import { useEffect, useRef, useState } from "react"; import { dynamicLoadCss, dynamicLoadJs } from "../../utils"; import CesiumMap from "./CesiumMap"; import "./index.less"; /** * 定位组件弹窗 */ const MapSelector = (props) => { const { visible, onClose, longitude, latitude, onConfirm, area = "", showArea = false, disable = false, type = "baidu", } = props; const mapContainerRef = useRef(null); const mapInstanceRef = useRef(null); const local = useRef(null); const [loading, setLoading] = useState(false); const [currentLongitude, setCurrentLongitude] = useState(longitude || ""); const [currentLatitude, setCurrentLatitude] = useState(latitude || ""); const [localSearch, setLocalSearch] = useState(""); const [currentArea, setCurrentArea] = useState(""); // 当外部经纬度变化时,更新内部状态 useEffect(() => { setCurrentLongitude(longitude || ""); setCurrentLatitude(latitude || ""); setCurrentArea(area || ""); }, [longitude, latitude, area]); // 百度地图初始化 const initBaiDuMap = () => { if (!window?.BMapGL?.Map) { setTimeout(() => { initBaiDuMap(); }, 50); return; } const map = new window.BMapGL.Map(mapContainerRef.current); mapInstanceRef.current = map; map.centerAndZoom( new window.BMapGL.Point( longitude || window.mapLongitude, latitude || window.mapLatitude, ), 16, ); map.enableScrollWheelZoom(true); // 如果有初始坐标,添加标记 if (longitude && latitude) { const point = new window.BMapGL.Point(longitude, latitude); const marker = new window.BMapGL.Marker(point); map.addOverlay(marker); } // 添加点击事件 if (!disable) { map.addEventListener("click", (event) => { map.clearOverlays(); const point = new window.BMapGL.Point(event.latlng.lng, event.latlng.lat); const marker = new window.BMapGL.Marker(point); map.addOverlay(marker); setCurrentLatitude(event.latlng.lat); setCurrentLongitude(event.latlng.lng); }); } }; // Cesium地图初始化 const initCesiumMap = () => { const { init, flyTo, addMarkPoint, getLongitudeAndLatitude } = new CesiumMap(); const { viewer } = init(); mapInstanceRef.current = viewer; flyTo({ longitude: longitude || window.mapLongitude, latitude: latitude || window.mapLatitude, height: 900000 }); if (longitude && latitude) { addMarkPoint({ longitude, latitude }); } getLongitudeAndLatitude((error, coords) => { if (error) return; const { longitude, latitude } = coords; setCurrentLatitude(latitude); setCurrentLongitude(longitude); }); }; // 初始化地图 const initMap = () => { setLoading(true); if (mapContainerRef.current) { // 只有在没有地图实例时才创建新地图 if (!mapInstanceRef.current) { if (type === "baidu") { initBaiDuMap(); return; } if (type === "cesium") { initCesiumMap(); } } setLoading(false); } }; // 加载百度地图资源 const loadBaiDuMap = async () => { if (!window.BMapGL) { if (window?.base?.loadDynamicResource) { await window.base.loadDynamicResource({ url: "https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OElqFYoKiAH8KFtph8ftLKF5NlNrbCUr&callback=initialize", type: "script", attr: { type: "text/javascript" }, }); initMap(); } else { await dynamicLoadJs("https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OElqFYoKiAH8KFtph8ftLKF5NlNrbCUr&callback=initialize"); initMap(); } } else { initMap(); } }; // 加载Cesium地图资源 const loadCesiumMap = async () => { if (!window.Cesium) { if (window?.base?.loadDynamicResource) { await window.base.loadDynamicResource({ url: "https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Cesium.js", type: "script", attr: { type: "text/javascript" }, }); await window.base.loadDynamicResource({ url: "https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Widgets/widgets.css", type: "link", attr: { rel: "stylesheet", type: "text/css" }, }); initMap(); } else { await dynamicLoadJs("https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Cesium.js"); await dynamicLoadCss("https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Widgets/widgets.css"); initMap(); } } else { initMap(); } }; // 加载地图资源 const loadMap = () => { if (!window.mapLongitude && !window.mapLatitude) { console.error("请在window设置变量 mapLongitude 和 mapLatitude,以供地图初始化坐标使用"); return; } if (type === "baidu") { loadBaiDuMap(); return; } if (type === "cesium") { loadCesiumMap(); } }; // 搜索功能 const handleLocalSearch = () => { if (localSearch && mapInstanceRef.current) { local.current = new window.BMapGL.LocalSearch(mapInstanceRef.current, { renderOptions: { map: mapInstanceRef.current }, }); local.current.search(localSearch); } }; // 清空 const handleLocalClear = () => { setLocalSearch(""); if (mapInstanceRef.current) { local.current.search(""); } }; // 关闭弹窗 const handleClose = () => { setLocalSearch(""); if (mapInstanceRef.current) { mapInstanceRef.current.destroy(); mapInstanceRef.current = null; } if (onClose) onClose(); }; // 确认选择 const handleConfirm = () => { if (onConfirm) { onConfirm(currentLongitude, currentLatitude, { area: currentArea }); } handleClose(); }; // 监听visible变化 useEffect(() => { let initTimer; if (visible) { // 延迟初始化地图,确保DOM完全渲染 initTimer = setTimeout(() => { loadMap(); }, 100); } return () => { if (initTimer) { clearTimeout(initTimer); } }; }, [visible]); const handleAfterClose = () => { if (mapInstanceRef.current) { try { mapInstanceRef.current.clearOverlays(); mapInstanceRef.current.destroy(); mapInstanceRef.current = null; } catch (e) { console.warn("Error destroying map on unmount:", e); } mapInstanceRef.current = null; } }; // 组件卸载时清理地图 useEffect(() => { return () => { handleAfterClose(); }; }, []); return ( 取消 , !disable && ( ), ]} >
{ showArea && ( ) } { (!disable && type === "baidu") && ( setLocalSearch(e.target.value)} allowClear /> ) }
); }; MapSelector.displayName = "MapSelector"; export default MapSelector;