From 025e1442a6f1b594fbc089da673d2e71034a267c Mon Sep 17 00:00:00 2001 From: LiuJiaNan <15703339975@163.com> Date: Mon, 5 Jan 2026 17:19:17 +0800 Subject: [PATCH] =?UTF-8?q?Map=E7=BB=84=E4=BB=B6=E5=A2=9E=E5=8A=A0cesium?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Map/CesiumMap.js | 186 ++++++++++++++++++++++++++++ src/components/Map/MapSelector.d.ts | 11 +- src/components/Map/h.png | Bin 0 -> 1491 bytes src/components/Map/index.d.ts | 2 + src/components/Map/index.js | 2 + src/components/Map/index.less | 5 + 6 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 src/components/Map/CesiumMap.js create mode 100644 src/components/Map/h.png create mode 100644 src/components/Map/index.less diff --git a/src/components/Map/CesiumMap.js b/src/components/Map/CesiumMap.js new file mode 100644 index 0000000..3bef133 --- /dev/null +++ b/src/components/Map/CesiumMap.js @@ -0,0 +1,186 @@ +import billboardImage from "./h.png"; + +export default class CesiumMap { + viewer; + currentMarkPointId; + init = () => { + const tianDiTuKey = "e8a16137fd226a62a23cc7ba5c9c78ce"; + const subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"]; + this.viewer = new window.Cesium.Viewer("map_container", { + // terrainProvider: window.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 window.Cesium.WebMapTileServiceImageryProvider({ + // 影像底图 + url: + `http://t{s}.tianditu.com/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=${ + tianDiTuKey}`, + subdomains, + layer: "tdtImgLayer", + style: "default", + format: "image/jpeg", + tileMatrixSetID: "GoogleMapsCompatible", // 使用谷歌的瓦片切片方式 + show: true, + }), + }); + this.viewer._cesiumWidget._creditContainer.style.display = "none"; // 隐藏cesium ion + this.viewer.imageryLayers.addImageryProvider( + new window.Cesium.WebMapTileServiceImageryProvider({ + // 影像注记 + url: + `http://t{s}.tianditu.com/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=${ + tianDiTuKey}`, + subdomains, + layer: "tdtCiaLayer", + style: "default", + format: "image/jpeg", + tileMatrixSetID: "GoogleMapsCompatible", + show: true, + }), + ); + this.initObliquePhotography(); + return { viewer: this.viewer }; + }; + + initObliquePhotography = () => { + this.viewer.scene.globe.depthTestAgainstTerrain = true; + window.Cesium.ExperimentalFeatures.enableModelExperimental = true; + const mapObliquePhotography = window.mapObliquePhotography || []; + for (let i = 0; i < mapObliquePhotography.length; i++) { + this.createObliquePhotography(mapObliquePhotography[i]); + } + }; + + createObliquePhotography = (url) => { + const tileset = new window.Cesium.Cesium3DTileset({ + url, + skipLevelOfDetail: true, + baseScreenSpaceError: 1024, + maximumScreenSpaceError: 128, // 数值加大,能让最终成像变模糊 + skipScreenSpaceErrorFactor: 16, + skipLevels: 1, + immediatelyLoadDesiredLevelOfDetail: false, + loadSiblings: true, // 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋 + cullWithChildrenBounds: true, + cullRequestsWhileMoving: true, + cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除 + preloadWhenHidden: true, + preferLeaves: true, + maximumMemoryUsage: 128, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验 + progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊 + dynamicScreenSpaceErrorDensity: 0.5, // 数值加大,能让周边加载变快 + dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先 + dynamicScreenSpaceError: true, // 有了这个后,会在真正的全屏加载完之后才清晰化房屋 + }); + + tileset.readyPromise.then((tileset) => { + // 笛卡尔转换为弧度 + + const cartographic = window.Cesium.Cartographic.fromCartesian( + tileset.boundingSphere.center, + ); + const lng = window.Cesium.Math.toDegrees(cartographic.longitude); // 使用经纬度和弧度的转换,将WGS84弧度坐标系转换到目标值,弧度转度 + const lat = window.Cesium.Math.toDegrees(cartographic.latitude); + // 计算中心点位置的地表坐标 + const surface = window.Cesium.Cartesian3.fromDegrees(lng, lat, 0); + // 偏移后的坐标 + const offset = window.Cesium.Cartesian3.fromDegrees(lng, lat, 5); + const translation = window.Cesium.Cartesian3.subtract( + offset, + surface, + new window.Cesium.Cartesian3(), + ); + tileset.modelMatrix = window.Cesium.Matrix4.fromTranslation(translation); + }); + this.viewer.scene.primitives.add(tileset); + }; + + flyTo = ({ longitude, latitude, height }) => { + this.viewer.camera.flyTo({ + destination: this.getPosition(longitude, latitude, height), + duration: 2, + }); + }; + + getPosition = (x, y, z = 0.0) => { + return window.Cesium.Cartesian3.fromDegrees(x, y, z); + }; + + clearMarkPoint = () => { + if (this.currentMarkPointId) { + this.viewer.entities.removeById(this.currentMarkPointId); + this.currentMarkPointId = null; + } + }; + + getLongitudeAndLatitude = (callback) => { + const handler = new window.Cesium.ScreenSpaceEventHandler( + this.viewer.scene.canvas, + ); + handler.setInputAction((click) => { + this.clearMarkPoint(); + const cartesian = this.viewer.camera.pickEllipsoid( + click.position, + this.viewer.scene.globe.ellipsoid, + ); + if (cartesian) { + const cartographic = window.Cesium.Cartographic.fromCartesian(cartesian); + const longitude = window.Cesium.Math.toDegrees(cartographic.longitude); + const latitude = window.Cesium.Math.toDegrees(cartographic.latitude); + this.currentMarkPointId = window.Cesium.createGuid(); + this.viewer.entities.add( + new window.Cesium.Entity({ + id: this.currentMarkPointId, + position: cartesian, + billboard: { + image: billboardImage, + width: 23, + height: 25, + verticalOrigin: window.Cesium.VerticalOrigin.BOTTOM, + horizontalOrigin: window.Cesium.HorizontalOrigin.CENTER, + heightReference: window.Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + clampToGround: true, + }, + }), + ); + if (callback && typeof callback === "function") + callback(null, { longitude, latitude }); + } + else { + if (callback && typeof callback === "function") + callback(new Error("无法获取坐标"), null); + } + }, window.Cesium.ScreenSpaceEventType.LEFT_CLICK); + }; + + addMarkPoint = ({ longitude, latitude }) => { + const cartesian = window.Cesium.Cartesian3.fromDegrees(longitude, latitude); + this.currentMarkPointId = window.Cesium.createGuid(); + this.viewer.entities.add( + new window.Cesium.Entity({ + id: this.currentMarkPointId, + position: cartesian, + billboard: { + image: billboardImage, + width: 23, + height: 25, + verticalOrigin: window.Cesium.VerticalOrigin.BOTTOM, + horizontalOrigin: window.Cesium.HorizontalOrigin.CENTER, + heightReference: window.Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + clampToGround: true, + }, + }), + ); + }; +} diff --git a/src/components/Map/MapSelector.d.ts b/src/components/Map/MapSelector.d.ts index aaeac97..d7f7a7f 100644 --- a/src/components/Map/MapSelector.d.ts +++ b/src/components/Map/MapSelector.d.ts @@ -1,14 +1,5 @@ import type { FC } from "react"; -export interface OnConfirmParams { - /** 经度值 */ - longitude: number | string; - /** 纬度值 */ - latitude: number | string; - /** 额外参数 */ - extra?: { area: string }; -} - export interface MapSelectorProps { /** 是否显示弹窗 */ visible: boolean; @@ -26,6 +17,8 @@ export interface MapSelectorProps { disable?: boolean; /** 确认选择回调 */ onConfirm?: (longitude: number | string, latitude: number | string, extra: { area: string }) => void; + /** 地图类型,默认 baidu */ + type?: "baidu" | "cesium"; } /** diff --git a/src/components/Map/h.png b/src/components/Map/h.png new file mode 100644 index 0000000000000000000000000000000000000000..31cec4a4f8d93446bbc76b3a2b5021143e38e523 GIT binary patch literal 1491 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6P!3HF6DQvv};*_{XlmzFem6RtIr7}3CY?O))XmO*Ar1(=|&rOfoV}vM^0aN`aY!O~0eDi?fr7i?gYtvzwuz ztCORFv5}*po2#RVo0+4tvlC3OXI^nhVqS78%|UUo?>$}CGwaVyHtRR9OFRVEe(5a)S_ z{uFWpPao(geNak4N;xngU~&X8;rRf_f#;;uJYe=I0_GE)K(R&!2F7omE{-7;x0X!v z)o=+EIeuPNp0n3*iVn}jH99&QKtOS+hUerUF)^_)v1?*VH~qwNR3^`Qqrv@2kh@yd z?93iR;}hXCPky$)S8M9~{p{?@_gB_`ez*JipXYn3{g(^wS|=R6WMN~`8D_SF0x#Hm z5AaWVz&WRZxqzi^v#`6#+xyce-Kugt;eF+$Xw#~V8qBH+&LPKZ65jh>e}1ns??aVX z%<5IAw|W*x2`t(ydgyCJh)3dPskqO-&E6=l0mC za<$LZA&-2Y>K#q3b5PZb$(qe{irY6WrfWH`cyMQY-A<9|Kf|>?epo%n*w6Rbd(ET4 zE-QPwl`9p!4!m7`#IQR<`Q3)9ncLa+txY?fHAmxD void; + /** 地图类型,默认 baidu */ + type?: "baidu" | "cesium"; } /** diff --git a/src/components/Map/index.js b/src/components/Map/index.js index 9f9223c..89370b5 100644 --- a/src/components/Map/index.js +++ b/src/components/Map/index.js @@ -13,6 +13,7 @@ const Map = (props) => { required = true, area = "", showArea = false, + type = "baidu", } = props; const form = Form.useFormInstance(); @@ -65,6 +66,7 @@ const Map = (props) => { longitude={currentLongitude} latitude={currentLatitude} area={area} + type={type} showArea={showArea} onConfirm={handleMapConfirm} /> diff --git a/src/components/Map/index.less b/src/components/Map/index.less new file mode 100644 index 0000000..1c00d89 --- /dev/null +++ b/src/components/Map/index.less @@ -0,0 +1,5 @@ +.cesium-viewer-toolbar, +.cesium-viewer-fullscreenContainer, +.cesium-infoBox-visible { + display: none !important; +}