2026-07-15 09:26:35 +08:00
|
|
|
|
import { useRef } from "react";
|
2026-01-05 14:53:49 +08:00
|
|
|
|
import { createObliquePhotography } from "~/pages/Container/Map/js/mapUtils";
|
2026-07-15 09:26:35 +08:00
|
|
|
|
import useMapMethods from "./mapMethods";
|
|
|
|
|
|
import usePointClickEvent from "./pointClickEvent";
|
2026-01-05 14:53:49 +08:00
|
|
|
|
|
|
|
|
|
|
const Cesium = window.Cesium;
|
|
|
|
|
|
|
2026-07-15 09:26:35 +08:00
|
|
|
|
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);
|
|
|
|
|
|
};
|
2026-01-05 14:53:49 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化地图
|
2026-07-15 09:26:35 +08:00
|
|
|
|
const initMap = () => {
|
2026-01-16 11:35:42 +08:00
|
|
|
|
const tianDiTuKey = "06494bcf2d4b66df7f3c586cc65af0cb";
|
2026-01-05 14:53:49 +08:00
|
|
|
|
const subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
|
2026-07-15 09:26:35 +08:00
|
|
|
|
viewer.current = new Cesium.Viewer("cesiumContainer", {
|
2026-01-05 14:53:49 +08:00
|
|
|
|
// terrainProvider: Cesium.createWorldTerrain()
|
|
|
|
|
|
animation: false, // 动画
|
|
|
|
|
|
homeButton: true, // home键
|
|
|
|
|
|
geocoder: true, // 地址编码
|
|
|
|
|
|
baseLayerPicker: false, // 图层选择控件
|
|
|
|
|
|
timeline: false, // 时间轴
|
|
|
|
|
|
fullscreenButton: true, // 全屏显示
|
|
|
|
|
|
infoBox: true, // 点击要素之后浮窗
|
|
|
|
|
|
sceneModePicker: true, // 投影方式 三维/二维
|
|
|
|
|
|
navigationInstructionsInitiallyVisible: false, // 导航指令
|
|
|
|
|
|
navigationHelpButton: false, // 帮助信息
|
|
|
|
|
|
selectionIndicator: false, // 选择
|
|
|
|
|
|
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
|
|
|
|
|
|
// 影像底图
|
|
|
|
|
|
url:
|
2026-01-16 11:35:42 +08:00
|
|
|
|
`https://t{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${
|
2026-01-05 14:53:49 +08:00
|
|
|
|
tianDiTuKey}`,
|
|
|
|
|
|
subdomains,
|
|
|
|
|
|
layer: "tdtImgLayer",
|
|
|
|
|
|
style: "default",
|
|
|
|
|
|
format: "image/jpeg",
|
|
|
|
|
|
tileMatrixSetID: "GoogleMapsCompatible", // 使用谷歌的瓦片切片方式
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
}),
|
|
|
|
|
|
});
|
2026-07-15 11:17:34 +08:00
|
|
|
|
// 调整 Cesium 默认相机操作:左键旋转地图,右键调整俯仰角,实现从平面俯视到立体视角的切换。
|
|
|
|
|
|
const cameraController = getViewer().scene.screenSpaceCameraController;
|
|
|
|
|
|
cameraController.rotateEventTypes = Cesium.CameraEventType.LEFT_DRAG;
|
|
|
|
|
|
cameraController.tiltEventTypes = [
|
|
|
|
|
|
Cesium.CameraEventType.RIGHT_DRAG,
|
|
|
|
|
|
Cesium.CameraEventType.MIDDLE_DRAG,
|
|
|
|
|
|
Cesium.CameraEventType.PINCH,
|
|
|
|
|
|
];
|
|
|
|
|
|
cameraController.zoomEventTypes = [
|
|
|
|
|
|
Cesium.CameraEventType.WHEEL,
|
|
|
|
|
|
Cesium.CameraEventType.PINCH,
|
|
|
|
|
|
];
|
2026-07-15 09:26:35 +08:00
|
|
|
|
getViewer()._cesiumWidget._creditContainer.style.display = "none"; // 隐藏cesium ion
|
|
|
|
|
|
getViewer().imageryLayers.addImageryProvider(
|
2026-01-05 14:53:49 +08:00
|
|
|
|
new Cesium.WebMapTileServiceImageryProvider({
|
|
|
|
|
|
// 影像注记
|
|
|
|
|
|
url:
|
2026-01-16 11:35:42 +08:00
|
|
|
|
`https://t{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=${
|
2026-01-05 14:53:49 +08:00
|
|
|
|
tianDiTuKey}`,
|
|
|
|
|
|
subdomains,
|
|
|
|
|
|
layer: "tdtCiaLayer",
|
|
|
|
|
|
style: "default",
|
|
|
|
|
|
format: "image/jpeg",
|
|
|
|
|
|
tileMatrixSetID: "GoogleMapsCompatible",
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
}),
|
|
|
|
|
|
);
|
2026-07-15 09:26:35 +08:00
|
|
|
|
initObliquePhotography();
|
|
|
|
|
|
registerClickEvent();
|
|
|
|
|
|
return { mapMethods: mapMethods.current, viewer: getViewer() };
|
2026-01-05 14:53:49 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-15 09:26:35 +08:00
|
|
|
|
// 外部入口进入港口:只有港口标识、名称和有效坐标齐全时才进入,避免 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,
|
2026-07-20 14:35:04 +08:00
|
|
|
|
markType: "港口",
|
2026-07-15 09:26:35 +08:00
|
|
|
|
isExternalEntry: "1",
|
|
|
|
|
|
position: { x: Number(longitude), y: Number(latitude) },
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
return true;
|
2026-01-05 14:53:49 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-15 09:26:35 +08:00
|
|
|
|
return {
|
|
|
|
|
|
viewer,
|
|
|
|
|
|
mapMethods,
|
|
|
|
|
|
initMap,
|
|
|
|
|
|
externalEntryPort,
|
2026-01-05 14:53:49 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|