From 42961e417ced03f221ded6735ee2b81b7e182d64 Mon Sep 17 00:00:00 2001 From: LiuJiaNan <15703339975@163.com> Date: Wed, 15 Jul 2026 09:26:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor(map):=20=E5=B0=86class=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=88=90hook=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Container/Map/index.js | 19 +- src/pages/Container/Map/js/initMap.js | 161 +++++++---- src/pages/Container/Map/js/mapMethods.js | 268 ++++++++++-------- src/pages/Container/Map/js/pointClickEvent.js | 150 +++++----- 4 files changed, 332 insertions(+), 266 deletions(-) diff --git a/src/pages/Container/Map/index.js b/src/pages/Container/Map/index.js index cda5463..00b5013 100644 --- a/src/pages/Container/Map/index.js +++ b/src/pages/Container/Map/index.js @@ -9,7 +9,7 @@ import Content from "./components/Content"; import Header from "./components/Header"; import RightUtils from "./components/RightUtils"; import { Context } from "./js/context"; -import InitMap from "./js/initMap"; +import useInitMap from "./js/initMap"; import mitt from "./js/mitt"; import { changeCoverMaskVisibleMittKey, @@ -20,9 +20,8 @@ import "./index.less"; function Map(props) { const query = useGetUrlQuery(); + const { viewer, mapMethods, initMap, externalEntryPort } = useInitMap(); - const viewer = useRef(null); // cesium地图实例 - const mapMethods = useRef(null); // cesium地图方法实例 const fullscreenRef = useRef(null); // 全屏容器的ref const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef); @@ -39,19 +38,17 @@ function Map(props) { sessionStorage.removeItem("mapCurrentBranchOfficeId"); - const initMap = new InitMap(); - const { viewer: viewerInstance, mapMethods: mapMethodsInstance } - = initMap.initMap(); - viewer.current = viewerInstance; - mapMethods.current = mapMethodsInstance; + initMap(); if (query.mapType === "港口") { - initMap.externalEntryPort(query); + const entered = externalEntryPort(query); + if (!entered) + message.warning("港口入口参数不完整,无法定位到对应港口"); } else { setTimeout(() => { - mapMethodsInstance.flyTo(); - mapMethodsInstance.addPortPoint(); + mapMethods.current.flyTo(); + mapMethods.current.addPortPoint(); }, 500); } diff --git a/src/pages/Container/Map/js/initMap.js b/src/pages/Container/Map/js/initMap.js index 988b0bb..3daad88 100644 --- a/src/pages/Container/Map/js/initMap.js +++ b/src/pages/Container/Map/js/initMap.js @@ -1,19 +1,74 @@ +import { useRef } from "react"; import { createObliquePhotography } from "~/pages/Container/Map/js/mapUtils"; -import MapMethods from "./mapMethods"; -import PointClickEvent from "./pointClickEvent"; +import useMapMethods from "./mapMethods"; +import usePointClickEvent from "./pointClickEvent"; const Cesium = window.Cesium; -export default class InitMap { - #pointClickEvent; - #viewer; - #mapMethods; +export default function useInitMap() { + // 页面和地图工具共用同一个 Cesium 引用,避免内外各维护一份实例。 + const viewer = useRef(null); + const mapMethodsValue = useMapMethods(viewer); + // Context 下游仍按 ref.current 调用地图方法,因此保留原有数据结构。 + const mapMethods = useRef(mapMethodsValue); + mapMethods.current = mapMethodsValue; + // 点位点击处理集合:替代原 PointClickEvent class 实例,负责弹窗和层级进入。 + const pointClickEvent = usePointClickEvent(viewer, mapMethodsValue); + + // 获取当前 Cesium 实例,减少内部方法对 ref 结构的重复感知。 + const getViewer = () => viewer.current; + + // 倾斜摄影 + const initObliquePhotography = () => { + getViewer().scene.globe.depthTestAgainstTerrain = true; + Cesium.ExperimentalFeatures.enableModelExperimental = true; + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/merge_tile.json", + getViewer(), + ); + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E8%A5%BF/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E8%A5%BF/merge_tile.json", + getViewer(), + ); + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/qhdxys/merge_tile.json", + getViewer(), + ); + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/qhdgysh/merge_tile.json", + getViewer(), + ); + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E8%A5%BF/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E8%A5%BF/merge_tile.json", + getViewer(), + ); + createObliquePhotography( + "http://192.168.192.215:8021/ware/upload/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E4%B8%9C/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E4%B8%9C/merge_tile.json", + getViewer(), + ); + }; + + // 注册点击事件 + const registerClickEvent = () => { + getViewer().cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); + getViewer().cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); + const screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(getViewer().scene.canvas); + screenSpaceEventHandler.setInputAction((movement) => { + const pick = getViewer().scene.pick(movement.position); + if (Cesium.defined(pick) && pick.id?.id) { + pointClickEvent.pointClickEvent(pick.id); + } + else { + pointClickEvent.closePopup(); + } + }, Cesium.ScreenSpaceEventType.LEFT_CLICK); + }; // 初始化地图 - initMap = () => { + const initMap = () => { const tianDiTuKey = "06494bcf2d4b66df7f3c586cc65af0cb"; const subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"]; - this.#viewer = new Cesium.Viewer("cesiumContainer", { + viewer.current = new Cesium.Viewer("cesiumContainer", { // terrainProvider: Cesium.createWorldTerrain() animation: false, // 动画 homeButton: true, // home键 @@ -39,8 +94,8 @@ export default class InitMap { show: true, }), }); - this.#viewer._cesiumWidget._creditContainer.style.display = "none"; // 隐藏cesium ion - this.#viewer.imageryLayers.addImageryProvider( + getViewer()._cesiumWidget._creditContainer.style.display = "none"; // 隐藏cesium ion + getViewer().imageryLayers.addImageryProvider( new Cesium.WebMapTileServiceImageryProvider({ // 影像注记 url: @@ -54,56 +109,48 @@ export default class InitMap { show: true, }), ); - this.#initObliquePhotography(); - this.#registerClickEvent(); - this.#mapMethods = new MapMethods(this.#viewer); - this.#pointClickEvent = new PointClickEvent(this.#viewer, this.#mapMethods); - return { mapMethods: this.#mapMethods, viewer: this.#viewer }; + initObliquePhotography(); + registerClickEvent(); + return { mapMethods: mapMethods.current, viewer: getViewer() }; }; - // 倾斜摄影 - #initObliquePhotography = () => { - this.#viewer.scene.globe.depthTestAgainstTerrain = true; - Cesium.ExperimentalFeatures.enableModelExperimental = true; - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/merge_tile.json", - this.#viewer, - ); - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E8%A5%BF/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E8%A5%BF/merge_tile.json", - this.#viewer, - ); - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/qhdxys/merge_tile.json", - this.#viewer, - ); - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/qhdgysh/merge_tile.json", - this.#viewer, - ); - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E8%A5%BF/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E8%A5%BF/merge_tile.json", - this.#viewer, - ); - createObliquePhotography( - "http://192.168.192.215:8021/ware/upload/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E4%B8%9C/%E6%B2%A7%E5%B7%9E%E6%B8%AF%E4%B8%9C/merge_tile.json", - this.#viewer, - ); + // 外部入口进入港口:只有港口标识、名称和有效坐标齐全时才进入,避免 Cesium 接收到无效坐标。 + const externalEntryPort = (data) => { + const id = data.id || data.portId; + const name = data.name || data.portName; + const longitude = data.position?.x ?? data.longitude ?? data.lng ?? data.x; + const latitude = data.position?.y ?? data.latitude ?? data.lat ?? data.y; + // 空字符串会被 Number 转成 0,需要先排除空值,再判断是否为有效数字。 + const hasCoordinate = value => value !== "" && value !== null && value !== undefined; + const hasValidPosition + = hasCoordinate(longitude) + && hasCoordinate(latitude) + && Number.isFinite(Number(longitude)) + && Number.isFinite(Number(latitude)); + + if (!id || !name || !hasValidPosition) + return false; + + pointClickEvent.pointClickEvent({ + monitorItems: { + data: { + ...data, + id, + name, + corpinfoId: data.corpinfoId, + mapType: "港口", + isExternalEntry: "1", + position: { x: Number(longitude), y: Number(latitude) }, + }, + }, + }); + return true; }; - // 注册点击事件 - #registerClickEvent = () => { - this.#viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); - this.#viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); - const screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(this.#viewer.scene.canvas); - screenSpaceEventHandler.setInputAction((movement) => { - const pick = this.#viewer.scene.pick(movement.position); - if (Cesium.defined(pick) && pick.id?.id) { - this.#pointClickEvent.pointClickEvent(pick.id); - } - else { - this.#pointClickEvent.closePopup(); - } - }, Cesium.ScreenSpaceEventType.LEFT_CLICK); + return { + viewer, + mapMethods, + initMap, + externalEntryPort, }; } diff --git a/src/pages/Container/Map/js/mapMethods.js b/src/pages/Container/Map/js/mapMethods.js index 119b6eb..2cd910a 100644 --- a/src/pages/Container/Map/js/mapMethods.js +++ b/src/pages/Container/Map/js/mapMethods.js @@ -1,3 +1,4 @@ +import { useRef } from "react"; import portEntityBillboardImage from "~/assets/images/map_bi/point/dianwei.png"; import branchOfficeEntityBillboardImage from "~/assets/images/map_bi/point/gongsidianwei.png"; import edgeCMT from "./edge/cmt.js"; @@ -18,6 +19,40 @@ import { chunkedLoad, filterNull, formatPolygon } from "./utils"; import "./TrajectoryPolylineTrailLinkMaterialProperty.js"; import "./WallPolylineTrailLinkMaterialProperty"; +const portPoint = [ + { + id: "00002", + name: "沧州黄骅港矿石港务有限公司", + introduce: + "公司现共有10个泊位(10-20万吨级),设计年通过能力6400万吨。堆场面积176万平米,堆存能力740万吨,大型装卸设备44台套。", + position: { x: 117.91412, y: 38.35902 }, + corpinfoId: "f8da1790b1034058ae2efefd69af3284", + }, + { + id: "00003", + name: "秦皇岛港", + introduce: + "秦皇岛港分为东、西两个港区,现有生产性泊位50个,年设计通过能力2.26亿吨,经营货类主要包括煤炭、金属矿石、油品及液体化工、集装箱及其他杂货等。", + position: { x: 119.61254, y: 39.92572 }, + }, + { + id: "00004", + name: "曹妃甸实业港务", + introduce: + "公司现共有6个泊位(5-30万吨级),设计年通过能力6550万吨。堆场面积146万平米,堆存能力1350万吨,大型装卸设备23台套。", + position: { x: 118.51022, y: 38.93503 }, + corpinfoId: "8854edee3aa94be496cee676b6d4845a", + }, + { + id: "00005", + name: "曹妃甸煤炭港务", + introduce: + "公司现共有5个泊位(5-10万吨级),设计年通过能力5000万吨。堆场面积83万平米,堆存能力373.5万吨,大型装卸设备19台套。", + position: { x: 118.43701, y: 38.9866 }, + corpinfoId: "6aa255d41602497fa0f934a822820df4", + }, +]; + const BranchOfficePoint = [ { corpName: "秦港股份有限公司", @@ -357,91 +392,59 @@ const BranchOfficePoint = [ }, ]; const Cesium = window.Cesium; -export default class MapMethods { - #viewer; - #defineCenterPoint = { +export default function useMapMethods(viewerRef) { + // 获取当前 Cesium 实例:初始化前为空,地图方法会在 initMap 完成后被调用。 + const getViewer = () => viewerRef.current; + + // 默认中心点:初始化和回到首页视角时使用,保持全局港区俯视高度。 + const defineCenterPoint = { longitude: 119.6486945226887, latitude: 39.93555616569192, height: 900000, - }; // 默认中心点 + }; - #currentCenterPoint = { + // 当前中心点:记录最近一次 flyTo 的视角,供外部按钮回到当前位置。 + const currentCenterPointRef = useRef({ longitude: 119.6486945226887, latitude: 39.93555616569192, height: 900000, - }; // 当前中心点 + }); - #previousCenterPoint = { + // 上一次中心点:从分公司返回港口层级时,需要回退到进入前的视角。 + const previousCenterPointRef = useRef({ longitude: 119.6486945226887, latitude: 39.93555616569192, height: 900000, - }; // 上一次中心点 - - constructor(viewer) { - this.#viewer = viewer; - } + }); // 设置中心点 - flyTo = ({ longitude, latitude, height } = this.#defineCenterPoint) => { - this.#viewer.camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); - this.#previousCenterPoint = { ...this.#currentCenterPoint }; - this.#currentCenterPoint = { longitude, latitude, height }; + const flyTo = ({ longitude, latitude, height } = defineCenterPoint) => { + getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); + previousCenterPointRef.current = { ...currentCenterPointRef.current }; + currentCenterPointRef.current = { longitude, latitude, height }; }; // 返回当前中心点 - returnCurrentCenterPoint = () => { - const { longitude, latitude, height } = this.#currentCenterPoint; - this.#viewer.camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); + const returnCurrentCenterPoint = () => { + const { longitude, latitude, height } = currentCenterPointRef.current; + getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); }; // 返回上一次中心点 - returnPreviousCenterPoint = () => { - const { longitude, latitude, height } = this.#previousCenterPoint; - this.#viewer.camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); - this.#currentCenterPoint = { longitude, latitude, height }; + const returnPreviousCenterPoint = () => { + const { longitude, latitude, height } = previousCenterPointRef.current; + getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 }); + currentCenterPointRef.current = { longitude, latitude, height }; }; // 切换场景模式 - changeSceneMode = (type = "3d") => { - this.#viewer.scene.mode = { "2d": Cesium.SceneMode.COLUMBUS_VIEW, "3d": Cesium.SceneMode.SCENE3D }[type]; + const changeSceneMode = (type = "3d") => { + getViewer().scene.mode = { "2d": Cesium.SceneMode.COLUMBUS_VIEW, "3d": Cesium.SceneMode.SCENE3D }[type]; }; // 添加港口点 - addPortPoint = async () => { - const portPoint = [ - { - id: "00002", - name: "沧州黄骅港矿石港务有限公司", - introduce: - "公司现共有10个泊位(10-20万吨级),设计年通过能力6400万吨。堆场面积176万平米,堆存能力740万吨,大型装卸设备44台套。", - position: { x: 117.91412, y: 38.35902 }, - corpinfoId: "f8da1790b1034058ae2efefd69af3284", - }, - { - id: "00003", - name: "秦皇岛港", - introduce: - "秦皇岛港分为东、西两个港区,现有生产性泊位50个,年设计通过能力2.26亿吨,经营货类主要包括煤炭、金属矿石、油品及液体化工、集装箱及其他杂货等。", - position: { x: 119.61254, y: 39.92572 }, - }, - { - id: "00004", - name: "曹妃甸实业港务", - introduce: - "公司现共有6个泊位(5-30万吨级),设计年通过能力6550万吨。堆场面积146万平米,堆存能力1350万吨,大型装卸设备23台套。", - position: { x: 118.51022, y: 38.93503 }, - corpinfoId: "8854edee3aa94be496cee676b6d4845a", - }, - { - id: "00005", - name: "曹妃甸煤炭港务", - introduce: - "公司现共有5个泊位(5-10万吨级),设计年通过能力5000万吨。堆场面积83万平米,堆存能力373.5万吨,大型装卸设备19台套。", - position: { x: 118.43701, y: 38.9866 }, - corpinfoId: "6aa255d41602497fa0f934a822820df4", - }, - ]; + const addPortPoint = async () => { await chunkedLoad(portPoint, 10, async (item) => { const entityCollection = createEntityCollection("portEntityCollection"); entityCollection.entities.add( @@ -453,18 +456,18 @@ export default class MapMethods { monitorItems: { data: { ...item, mapType: "港口" } }, }), ); - this.#viewer.dataSources.add(entityCollection); + getViewer().dataSources.add(entityCollection); }); - await addMergedEntityCollection(this.#viewer, "portEntityCollection"); + await addMergedEntityCollection(getViewer(), "portEntityCollection"); }; // 移除港口点 - removePortPoint = () => { - removeEntityCollection(this.#viewer, "portEntityCollectionMerged"); + const removePortPoint = () => { + removeEntityCollection(getViewer(), "portEntityCollectionMerged"); }; // 添加分公司点 - addBranchOfficePoint = async (area = "", pointInfo = null) => { + const addBranchOfficePoint = async (area = "", pointInfo = null) => { mitt.emit(changeCoverMaskVisibleMittKey, true); let branchOfficePoint = []; if (!pointInfo) { @@ -486,19 +489,19 @@ export default class MapMethods { }, }), ); - this.#viewer.dataSources.add(entityCollection); + getViewer().dataSources.add(entityCollection); }); - await addMergedEntityCollection(this.#viewer, "branchOfficeEntityCollection"); + await addMergedEntityCollection(getViewer(), "branchOfficeEntityCollection"); mitt.emit(changeCoverMaskVisibleMittKey, false); }; // 删除分公司点 - removeBranchOfficePoint = () => { - removeEntityCollection(this.#viewer, "branchOfficeEntityCollectionMerged"); + const removeBranchOfficePoint = () => { + removeEntityCollection(getViewer(), "branchOfficeEntityCollectionMerged"); }; // 添加四色图 - addFourColorDiagram = (id, corpionId) => { + const addFourColorDiagram = (id, corpionId) => { const edgeMap = { "00003": edgeQHD, "00002": edgeCZKS, @@ -551,17 +554,17 @@ export default class MapMethods { ); }); - this.#viewer.dataSources.add(entityCollection); + getViewer().dataSources.add(entityCollection); mitt.emit(changeCoverMaskVisibleMittKey, false); }; // 删除四色图 - removeFourColorDiagram = () => { - removeEntityCollection(this.#viewer, "fourColorDiagramEntityCollection"); + const removeFourColorDiagram = () => { + removeEntityCollection(getViewer(), "fourColorDiagramEntityCollection"); }; // 添加墙 - addWall = (id, corpionId) => { + const addWall = (id, corpionId) => { const edgeMap = { "00003": edgeQHD, "00002": edgeCZKS, @@ -592,7 +595,7 @@ export default class MapMethods { id: createId(), wall: { positions, - material: new Cesium.WallPolylineTrailLinkMaterialProperty(this.#viewer), + material: new Cesium.WallPolylineTrailLinkMaterialProperty(getViewer()), maximumHeights: Array.from({ length: pointCount }).fill(40), minimumHeights: Array.from({ length: pointCount }).fill(0), }, @@ -600,63 +603,17 @@ export default class MapMethods { ); }); - this.#viewer.dataSources.add(entityCollection); + getViewer().dataSources.add(entityCollection); mitt.emit(changeCoverMaskVisibleMittKey, false); }; // 删除墙 - removeWall = () => { - removeEntityCollection(this.#viewer, "wallEntityCollection"); - }; - - /** - * desc: 添加点位 - * @param {Array} pointList - * @param options {Object: {mapIcon, type, subLabel}} 配置项 - * @param options.mapIcon {String} 扎点图标 - * @param options.mapType {String} 扎点类型 - * @param options.subLabel {String} 二级标题(用于弹窗标题) - */ - addMarkPoint = async (pointList, options) => { - if (!options.mapType) - throw new Error("请传入mapType(扎点类型)"); - if (!options.mapIcon) - throw new Error("请传入mapIcon(扎点图标)"); - mitt.emit(changeCoverMaskVisibleMittKey, true); - await chunkedLoad(pointList, 10, async (item) => { - const entityCollection = createEntityCollection( - `markEntityCollection_${options.mapType}`, - ); - const name = item.MAP_POINT_NAME || item.AREA_NAME || ""; - entityCollection.entities.add( - new Cesium.Entity({ - id: createId(), - name, - position: getPosition(item.LONGITUDE, item.LATITUDE), - billboard: await getBillboard({ image: options.mapIcon, name }), - monitorItems: { - data: { ...item, mapType: `标记点_${options.mapType}`, subLabel: options.subLabel }, - }, - }), - ); - this.#viewer.dataSources.add(entityCollection); - }); - const dataSource = await addMergedEntityCollection( - this.#viewer, - "markEntityCollection", - options.mapType, - ); - this.#enabledClustering(dataSource); - mitt.emit(changeCoverMaskVisibleMittKey, false); - }; - - // 删除点位 - removeMarkPoint = (mapType) => { - removeEntityCollection(this.#viewer, `markEntityCollectionMerged${mapType ? `_${mapType}` : ""}`); + const removeWall = () => { + removeEntityCollection(getViewer(), "wallEntityCollection"); }; // 点位聚合 - #enabledClustering = (dataSource) => { + const enabledClustering = (dataSource) => { dataSource.clustering.enabled = true; // 聚合开启 dataSource.clustering.pixelRange = 50; // 设置像素范围,以扩展显示边框 dataSource.clustering.minimumClusterSize = 5; // 设置最小的聚合点数目,超过此数目才能聚合 @@ -719,4 +676,67 @@ export default class MapMethods { dataSource.clustering.pixelRange = pixelRange; } }; + + /** + * desc: 添加点位 + * @param {Array} pointList + * @param options {Object: {mapIcon, type, subLabel}} 配置项 + * @param options.mapIcon {String} 扎点图标 + * @param options.mapType {String} 扎点类型 + * @param options.subLabel {String} 二级标题(用于弹窗标题) + */ + const addMarkPoint = async (pointList, options) => { + if (!options.mapType) + throw new Error("请传入mapType(扎点类型)"); + if (!options.mapIcon) + throw new Error("请传入mapIcon(扎点图标)"); + mitt.emit(changeCoverMaskVisibleMittKey, true); + await chunkedLoad(pointList, 10, async (item) => { + const entityCollection = createEntityCollection( + `markEntityCollection_${options.mapType}`, + ); + const name = item.MAP_POINT_NAME || item.AREA_NAME || ""; + entityCollection.entities.add( + new Cesium.Entity({ + id: createId(), + name, + position: getPosition(item.LONGITUDE, item.LATITUDE), + billboard: await getBillboard({ image: options.mapIcon, name }), + monitorItems: { + data: { ...item, mapType: `标记点_${options.mapType}`, subLabel: options.subLabel }, + }, + }), + ); + getViewer().dataSources.add(entityCollection); + }); + const dataSource = await addMergedEntityCollection( + getViewer(), + "markEntityCollection", + options.mapType, + ); + enabledClustering(dataSource); + mitt.emit(changeCoverMaskVisibleMittKey, false); + }; + + // 删除点位 + const removeMarkPoint = (mapType) => { + removeEntityCollection(getViewer(), `markEntityCollectionMerged${mapType ? `_${mapType}` : ""}`); + }; + + return { + flyTo, + returnCurrentCenterPoint, + returnPreviousCenterPoint, + changeSceneMode, + addPortPoint, + removePortPoint, + addBranchOfficePoint, + removeBranchOfficePoint, + addFourColorDiagram, + removeFourColorDiagram, + addWall, + removeWall, + addMarkPoint, + removeMarkPoint, + }; } diff --git a/src/pages/Container/Map/js/pointClickEvent.js b/src/pages/Container/Map/js/pointClickEvent.js index da1ac37..0697751 100644 --- a/src/pages/Container/Map/js/pointClickEvent.js +++ b/src/pages/Container/Map/js/pointClickEvent.js @@ -1,3 +1,4 @@ +import { useRef } from "react"; import BranchOffice from "../components/popup/components/BranchOffice"; import Port from "../components/popup/components/Port"; import PopupInfo from "../components/popup/js/PopupInfo"; @@ -12,71 +13,35 @@ import { resetBottomCurrentIndexMittKey, } from "./mittKey"; -export default class PointClickEvent { - #viewer; - #popup; - #mapMethods; +export default function usePointClickEvent(viewerRef, mapMethods) { + const popupRef = useRef(null); - constructor(viewer, mapMethods) { - this.#viewer = viewer; - this.#mapMethods = mapMethods; - } + // 获取当前 Cesium 实例:点击事件触发时地图已经完成初始化。 + const getViewer = () => viewerRef.current; // 关闭弹窗 - closePopup = () => { - if (this.#popup) { - this.#popup.remove(); - this.#popup = null; + const closePopup = () => { + if (popupRef.current) { + popupRef.current.remove(); + popupRef.current = null; } }; - // 点位点击 - pointClickEvent = (pick) => { - const data = pick.monitorItems.data; - this.closePopup(); - if (data.isExternalEntry === "1" && data.mapType === "港口") { - this.#clickPortPointEnter(data); - return; - } - if (data.mapType === "港口") - this.#clickPortPoint(data); - if (data.mapType === "分公司") - this.#clickBranchOfficePoint(data); - if (data.mapType.includes("标记点")) - this.#clickMarkPoint(data); - }; - - // 港口点位点击 - #clickPortPoint = (data) => { - const position = getPosition(data.position.x, data.position.y); - this.#popup = new PopupInfo(this.#viewer, { - component: Port, - position, - props: { - info: data, - close: this.closePopup, - enter: () => { - this.#clickPortPointEnter(data); - }, - }, - }); - }; - // 港口点位点击进入 - #clickPortPointEnter = (data) => { - this.closePopup(); - this.#mapMethods.removePortPoint(); + const clickPortPointEnter = (data) => { + closePopup(); + mapMethods.removePortPoint(); // setTimeout(() => { if (data.id === "00003") { - this.#mapMethods.flyTo({ longitude: data.position.x, latitude: data.position.y, height: 10000 }); - this.#mapMethods.addBranchOfficePoint(); + mapMethods.flyTo({ longitude: data.position.x, latitude: data.position.y, height: 10000 }); + mapMethods.addBranchOfficePoint(); mitt.emit(clickPortPointMittKey, data); } else { - this.#mapMethods.removeFourColorDiagram(); - this.#mapMethods.removeWall(); - this.#mapMethods.flyTo({ longitude: data.position.x, latitude: data.position.y, height: 2000 }); - this.#mapMethods.addBranchOfficePoint("", { + mapMethods.removeFourColorDiagram(); + mapMethods.removeWall(); + mapMethods.flyTo({ longitude: data.position.x, latitude: data.position.y, height: 2000 }); + mapMethods.addBranchOfficePoint("", { corpName: data.name, corpinfoId: data.corpinfoId, longitude: data.position.x, @@ -91,35 +56,31 @@ export default class PointClickEvent { mitt.emit(resetAllBottomUtilsCheckMittKey); }; - // 分公司点位点击 - #clickBranchOfficePoint = async (data) => { - if (data.id === sessionStorage.getItem("mapCurrentBranchOfficeId")) - return; - // const { info } = await getCorpInfo({ id: data.id }); - const info = {}; - const position = getPosition(data.longitude, data.latitude); - this.#popup = new PopupInfo(this.#viewer, { - component: BranchOffice, + // 港口点位点击 + const clickPortPoint = (data) => { + const position = getPosition(data.position.x, data.position.y); + popupRef.current = new PopupInfo(getViewer(), { + component: Port, position, props: { - info, - close: this.closePopup, + info: data, + close: closePopup, enter: () => { - this.#clickBranchOfficePointEnter(data); + clickPortPointEnter(data); }, }, }); }; // 分公司点位点击进入 - #clickBranchOfficePointEnter = (data) => { - this.closePopup(); - this.#mapMethods.removeBranchOfficePoint(); - this.#mapMethods.removeMarkPoint(); - this.#mapMethods.addBranchOfficePoint("", data); - this.#mapMethods.removeFourColorDiagram(); - this.#mapMethods.removeWall(); - this.#mapMethods.flyTo({ longitude: data.longitude, latitude: data.latitude, height: 2000 }); + const clickBranchOfficePointEnter = (data) => { + closePopup(); + mapMethods.removeBranchOfficePoint(); + mapMethods.removeMarkPoint(); + mapMethods.addBranchOfficePoint("", data); + mapMethods.removeFourColorDiagram(); + mapMethods.removeWall(); + mapMethods.flyTo({ longitude: data.longitude, latitude: data.latitude, height: 2000 }); mitt.emit(deletePeoplePositionPointMittKey); mitt.emit(clickBranchOfficePointMittKey, data); sessionStorage.setItem("mapCurrentBranchOfficeId", data.corpinfoId); @@ -127,8 +88,49 @@ export default class PointClickEvent { mitt.emit(resetAllBottomUtilsCheckMittKey); }; + // 分公司点位点击 + const clickBranchOfficePoint = async (data) => { + if (data.id === sessionStorage.getItem("mapCurrentBranchOfficeId")) + return; + // const { info } = await getCorpInfo({ id: data.id }); + const info = {}; + const position = getPosition(data.longitude, data.latitude); + popupRef.current = new PopupInfo(getViewer(), { + component: BranchOffice, + position, + props: { + info, + close: closePopup, + enter: () => { + clickBranchOfficePointEnter(data); + }, + }, + }); + }; + // 标记点位点击 - #clickMarkPoint = (data) => { + const clickMarkPoint = (data) => { mitt.emit(clickMarkPointMittKey, data); }; + + // 点位点击 + const pointClickEvent = (pick) => { + const data = pick.monitorItems.data; + closePopup(); + if (data.isExternalEntry === "1" && data.mapType === "港口") { + clickPortPointEnter(data); + return; + } + if (data.mapType === "港口") + clickPortPoint(data); + if (data.mapType === "分公司") + clickBranchOfficePoint(data); + if (data.mapType.includes("标记点")) + clickMarkPoint(data); + }; + + return { + closePopup, + pointClickEvent, + }; }