Map组件增加cesium地图

master
LiuJiaNan 2026-01-05 17:19:17 +08:00
parent e934ab4168
commit 025e1442a6
6 changed files with 197 additions and 9 deletions

View File

@ -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,
},
}),
);
};
}

View File

@ -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";
}
/**

BIN
src/components/Map/h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -13,6 +13,8 @@ export interface MapProps {
showArea?: boolean;
/** 确认选择回调 */
onConfirm?: (longitude: number | string, latitude: number | string, extra: { area: string }) => void;
/** 地图类型,默认 baidu */
type?: "baidu" | "cesium";
}
/**

View File

@ -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}
/>

View File

@ -0,0 +1,5 @@
.cesium-viewer-toolbar,
.cesium-viewer-fullscreenContainer,
.cesium-infoBox-visible {
display: none !important;
}