LSSE-front/src/components/Common/Cesium/index.js

218 lines
7.7 KiB
JavaScript
Raw Normal View History

2025-08-11 15:24:06 +08:00
import * as Cesium from 'cesium'
import CesiumNavigation from 'cesium-navigation-es6'
import 'cesium/Build/Cesium/Widgets/widgets.css'
const getCatesian3FromPX = (viewer, px) => {
const picks = viewer.scene.drillPick(px)
viewer.scene.render()
let cartesian
let isOn3dtiles = false
for (var i = 0; i < picks.length; i++) {
if (picks[i] && picks[i].primitive && picks[i].primitive instanceof Cesium.Cesium3DTileset) {
//模型上拾取
isOn3dtiles = true
break
}
}
if (isOn3dtiles) {
cartesian = viewer.scene.pickPosition(px)
} else {
var ray = viewer.camera.getPickRay(px)
if (!ray) return null
cartesian = viewer.scene.globe.pick(ray, viewer.scene)
}
return cartesian
}
2025-08-11 15:24:06 +08:00
export default class MyCesium {
static ImageryProviderUrl = '/map/mapWX/{z}/{x}/{y}.jpg'
2025-08-11 15:24:06 +08:00
static RoadProviderUrl = ''
static TerrainProviderUrl = '/map/mapDem/'
2025-08-11 15:24:06 +08:00
static center = [116.39742, 39.90906, 2000000]
static ENTITY_TYPES = {
WARZONE: 1,
SAFEZONE: 2,
MODEL: 3,
IMAGE: 4,
ROUTE: 5,
LINE: 6, // 两个模型之间的连线
POINT_PLANNING: 7, // 规划点
GRAPHICS: 8, // 折线
AIR_ROUTE: 9, // 航路
ROAMING_PLANE: 10,
}
viewer = null
// 未完成的在地图上移动类的操作
operations = []
// 已添加的军标
plots = []
2025-08-11 15:24:06 +08:00
2025-08-16 10:13:46 +08:00
constructor(dom, options = {}) {
2025-08-11 15:24:06 +08:00
const imageryProvider = new Cesium.UrlTemplateImageryProvider({
url: window._CONFIG.ImageryProviderUrl || MyCesium.ImageryProviderUrl,
tilingScheme: new Cesium.WebMercatorTilingScheme(),
maximumLevel: 15,
})
const roadProvider = new Cesium.UrlTemplateImageryProvider({
url: window._CONFIG.RoadProviderUrl || MyCesium.RoadProviderUrl,
tilingScheme: new Cesium.WebMercatorTilingScheme(),
maximumLevel: 15,
format: 'image/png',
})
const terrainProvider = new Cesium.CesiumTerrainProvider({
url: window._CONFIG.TerrainProviderUrl || MyCesium.TerrainProviderUrl,
})
const viewer = new Cesium.Viewer(dom, {
shouldAnimate: true, // 粒子效果
geocoder: false, // 是否显示位置查找工具true表示是false表示否
homeButton: false, // 是否显示首页位置工具
sceneModePicker: false, // 是否显示视角模式切换工具
baseLayerPicker: false, // 是杏显示默认图层选择工具
navigationHelpButton: false, // 是否显示导航帮助工具
animation: false, // 是杏显示动画工具
timeline: false, // 是否显示时间轴工具
fullscreenButton: false, // 是否显示全屏按钮工具
imageryProvider,
terrainProvider,
infoBox: false, // 是否显示信息框
selectionIndicator: false, // 是否显示选中实体时的绿框
})
this.viewer = viewer
2025-08-16 10:13:46 +08:00
const { center = MyCesium.center } = options
2025-08-11 15:24:06 +08:00
// viewer.scene.globe.depthTestAgainstTerrain = true
viewer.imageryLayers.addImageryProvider(roadProvider)
viewer.camera.setView({
2025-08-16 10:13:46 +08:00
destination: Cesium.Cartesian3.fromDegrees(...center),
2025-08-11 15:24:06 +08:00
})
// 不显示Cesium的Logo
viewer._cesiumWidget._creditContainer.style.display = 'none'
viewer.scene.sun.show = true //太阳和月亮
viewer.scene.moon.show = true
viewer.scene.skyAtmosphere.show = true //大气层,显示天空颜色
// 设置外天空盒
viewer.scene.skyBox = new Cesium.SkyBox({
sources: {
positiveX: '/images/Standard-Cube-Map/px1.png',
negativeX: '/images/Standard-Cube-Map/nx1.png',
positiveY: '/images/Standard-Cube-Map/pz.png',
negativeY: '/images/Standard-Cube-Map/nz1.png',
positiveZ: '/images/Standard-Cube-Map/py.png',
negativeZ: '/images/Standard-Cube-Map/ny1.png',
},
})
viewer.scene.skyBox.show = true //天空盒
// 创建指北针小部件并将其添加到地图
new CesiumNavigation(viewer, {
// 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.
2025-08-16 10:13:46 +08:00
defaultResetView: Cesium.Cartographic.fromDegrees(...center),
2025-08-11 15:24:06 +08:00
// 用于启用或禁用罗盘。true是启用罗盘false是禁用罗盘。默认值为true。如果将选项设置为false则罗盘将不会添加到地图中。
enableCompass: true,
// 用于启用或禁用缩放控件。true是启用false是禁用。默认值为true。如果将选项设置为false则缩放控件 将不会添加到地图中。
enableZoomControls: true,
// 用于启用或禁用距离图例。true是启用false是禁用。默认值为true。如果将选项设置为false距离图例将不会添加到地图中。
enableDistanceLegend: true,
// 用于启用或禁用指南针外环。true是启用false是禁用。默认值为true。如果将选项设置为false则该环将可见但无效。
enableCompassOuterRing: true,
})
}
// 取消未完成的在地图上移动类的操作(划线之类的)
cancelPreviousOperation() {
this.operations.forEach((operation) => operation.clear())
this.operations = []
}
/**
* 根据四个角落坐标确定视口位置
* @param leftUp
* @param rightUp
* @param rightDown
* @param leftDown
2025-08-11 15:24:06 +08:00
*/
setClientByAllCorner(leftUp, rightUp, rightDown, leftDown) {
2025-08-16 10:13:46 +08:00
const [leftUpLon, leftUpLat] = leftUp
const [rightUpLon, rightUpLat] = rightUp
const [rightDownLon, rightDownLat] = rightDown
const [leftDownLon, leftDownLat] = leftDown
// 计算矩形区域的边界
const west = Math.min(leftDownLon, leftUpLon, rightDownLon, rightUpLon)
const east = Math.max(leftDownLon, leftUpLon, rightDownLon, rightUpLon)
const south = Math.min(leftDownLat, leftUpLat, rightDownLat, rightUpLat)
const north = Math.max(leftDownLat, leftUpLat, rightDownLat, rightUpLat)
// 创建矩形范围
const rectangle = Cesium.Rectangle.fromDegrees(west, south, east, north)
this.viewer.camera.setView({
destination: rectangle,
orientation: {
heading: 0.0,
pitch: -Cesium.Math.PI_OVER_TWO,
roll: 0.0,
},
})
}
/**
* 添加军标(base64图片)
* @param base64
* @param x
* @param y
*/
addPlot(base64, screenPosition) {
this.cancelPreviousOperation()
const position = getCatesian3FromPX(this.viewer, screenPosition)
if (!position) return false
const id = Cesium.createGuid()
const isEnemy = false
const color = 'red'
const radius = 150000
const plot = {
id,
position,
billboard: {
image: base64,
width: 50,
height: 50,
eyeOffset: new Cesium.Cartesian3(0.0, 0.0, -100000.0), // 使标记在远处看起来更大
},
ellipse: {
semiMajorAxis: radius,
semiMinorAxis: radius,
material: Cesium.Color.fromCssColorString('transparent'),
outline: true,
outlineWidth: 1,
outlineColor: Cesium.Color.fromCssColorString(color),
height: 0,
},
properties: {
type: MyCesium.ENTITY_TYPES.IMAGE,
color,
isEnemy,
radius,
collisions: new Set(),
},
}
this.viewer.entities.add(plot)
this.plots.push(plot)
// 1. 将屏幕坐标转换为世界坐标(在椭球体表面)
const cartesian = this.viewer.camera.pickEllipsoid(screenPosition, this.viewer.scene.globe.ellipsoid)
if (Cesium.defined(cartesian)) {
// 2. 将世界坐标 (Cartesian3) 转换为地理坐标 Cartographic (弧度)
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
// 3. 将弧度转换为度数
const longitude = Cesium.Math.toDegrees(cartographic.longitude)
const latitude = Cesium.Math.toDegrees(cartographic.latitude)
return { plotId: id, longitude, latitude }
}
}
2025-08-11 15:24:06 +08:00
}