LSSE-front/src/components/Common/Cesium/index.js
2025-08-11 15:24:06 +08:00

279 lines
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as Cesium from 'cesium'
import CesiumNavigation from 'cesium-navigation-es6'
import 'cesium/Build/Cesium/Widgets/widgets.css'
export default class MyCesium {
static ImageryProviderUrl = 'http://localhost:8090/mapWX/{z}/{x}/{y}.jpg'
static RoadProviderUrl = ''
static TerrainProviderUrl = 'http://localhost:8090/mapDem/'
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
// 选中模型
selectedModel = null
// 右鍵菜單
contextMenu = {
visible: false,
left: 0,
top: 0,
}
// 未完成的在地图上移动类的操作
operations = []
constructor(dom) {
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
// viewer.scene.globe.depthTestAgainstTerrain = true
viewer.imageryLayers.addImageryProvider(roadProvider)
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(...MyCesium.center),
})
// 不显示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.
defaultResetView: Cesium.Cartographic.fromDegrees(...MyCesium.center),
// 用于启用或禁用罗盘。true是启用罗盘false是禁用罗盘。默认值为true。如果将选项设置为false则罗盘将不会添加到地图中。
enableCompass: true,
// 用于启用或禁用缩放控件。true是启用false是禁用。默认值为true。如果将选项设置为false则缩放控件 将不会添加到地图中。
enableZoomControls: true,
// 用于启用或禁用距离图例。true是启用false是禁用。默认值为true。如果将选项设置为false距离图例将不会添加到地图中。
enableDistanceLegend: true,
// 用于启用或禁用指南针外环。true是启用false是禁用。默认值为true。如果将选项设置为false则该环将可见但无效。
enableCompassOuterRing: true,
})
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
handler.setInputAction(({ position }) => {
if (this.selectedModel) {
this.deselectModel(this.selectedModel)
this.selectedModel = null
}
const pickedObject = viewer.scene.pick(position)
if (!Cesium.defined(pickedObject) || !pickedObject.id) {
window.Emit('pickedObject', null)
return
}
const entity = pickedObject.id
if (
!entity.properties ||
(entity.properties.type != MyCesium.ENTITY_TYPES.MODEL && entity.properties.type != MyCesium.ENTITY_TYPES.IMAGE)
) {
window.Emit('pickedObject', null)
return
}
this.selectedModel = entity
this.selectModel(entity)
window.Emit('selectedModel', {
id: entity.id,
})
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
// 鼠标右键事件
handler.setInputAction(({ position }) => {
const pickedObject = viewer.scene.pick(position)
if (!Cesium.defined(pickedObject) || !pickedObject.id) return
const entity = pickedObject.id
const properties = entity.properties
if (
!properties ||
!properties.type ||
(properties.type != MyCesium.ENTITY_TYPES.MODEL && properties.type != MyCesium.ENTITY_TYPES.IMAGE)
) {
return
}
const nomove = properties.nomove
if (selectedModel && entity.id == selectedModel.id && !(nomove && nomove.valueOf())) {
this.showContextMenu(entity)
this.cancelPreviousOperation()
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
// shift + 左键事件
handler.setInputAction(
({ position }) => {
const pickedObject = viewer.scene.pick(position)
if (!Cesium.defined(pickedObject) || !pickedObject.id) return
const entity = pickedObject.id
if (!entity.properties || entity.properties.type != MyCesium.ENTITY_TYPES.MODEL) return
if (this.selectedModel) {
// 找到已有的properties中的from和to是选中的两个模型的id的线
const find = viewer.entities.values.find((item) => {
const props = item.properties
if (!props || !props.type || !props.from || !props.to) return false
return (
(props.from == this.selectedModel.id && props.to == entity.id) ||
(props.from == entity.id && props.to == this.selectedModel.id)
)
})
// 如果已经有了,移除
if (find) {
viewer.entities.remove(find)
const { from, to } = find.properties
// 发送删除线的事件
window.Emit('removeLineBetwenModel', {
id: find.id,
from: from.valueOf(),
to: to.valueOf(),
})
} else {
const id = Cesium.createGuid()
const currentTime = viewer.clock.currentTime
const positions = [this.selectedModel.position.getValue(currentTime), entity.position.getValue(currentTime)]
if (positions.some((item) => !item)) {
console.log('缺少位置信息')
return
}
this.addLineBetwenModel(id, positions, selectedModel.id, entity.id)
// 发送添加线的事件
window.Emit('addLineBetwenModel', {
positions,
id,
from: selectedModel.id,
to: entity.id,
})
}
}
},
Cesium.ScreenSpaceEventType.LEFT_CLICK,
Cesium.KeyboardEventModifier.SHIFT
)
}
/**
* 选中模型
* @param {Cesium.Entity} entity
*/
selectModel(entity) {
if (!entity.model) return
const {
properties: { color: _color },
} = entity
const color = _color.valueOf()
// 设置模型轮廓效果
entity.model.silhouetteSize = 2 // 轮廓线宽度
entity.model.silhouetteColor = Cesium.Color.fromCssColorString(color)
entity.label.show = true
}
/**
* 取消选中模型
* @param {Cesium.Entity} entity
*/
deselectModel(entity) {
if (!entity.model) return
entity.model.silhouetteSize = 0 // 设置为0取消轮廓
entity.label.show = false
}
/**
* 显示右键菜单
* @param {Cesium.Entity} entity
*/
showContextMenu(entity) {
const currentTime = viewer.clock.currentTime
// 获取entity中心点的屏幕坐标
const position = entity.position.getValue(currentTime)
const screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, position)
this.contextMenu.left = screenPosition.x + 20
this.contextMenu.top = screenPosition.y
this.contextMenu.visible = true
}
// 取消未完成的在地图上移动类的操作(划线之类的)
cancelPreviousOperation() {
this.operations.forEach((operation) => operation.clear())
this.operations = []
}
/**
* 在模型之间添加线
* @param id
* @param { Cesium.Cartesian3[] } positions
* @param fromId
* @param toId
*/
addLineBetwenModel(id, positions, fromId, toId) {
this.viewer.entities.add({
id,
polyline: {
positions,
width: 2,
material: new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.YELLOW,
dashLength: 20, //短划线长度
}),
clampToGround: true,
},
properties: {
type: MyCesium.ENTITY_TYPES.LINE,
from: fromId,
to: toId,
},
})
}
}