import * as mars3d from "mars3d"
export let map // mars3d.Map三维地图对象
export let graphicLayer
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
export const mapOptions = {
scene: {
shadows: true,
center: { lat: 12.845055, lng: 112.931363, alt: 24286797, heading: 3, pitch: -90 },
cameraController: {
zoomFactor: 3.0,
minimumZoomDistance: 1000,
maximumZoomDistance: 300000000,
constrainedAxis: false // 解除在南北极区域鼠标操作限制
},
globe: { enableLighting: true },
clock: {
multiplier: 1 // 速度
}
},
control: {
clockAnimate: true, // 时钟动画控制(左下角)
timeline: true, // 是否显示时间线控件
compass: { top: "10px", left: "5px" }
},
layers: [
{
name: "夜晚图片",
icon: "img/basemaps/blackMarble.png",
type: "image",
url: "//data.mars3d.cn/file/img/world/night2.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5,
show: true
}
]
}
/**
* 初始化地图业务,生命周期钩子函数(必须)
* 框架在地图初始化完成后自动调用该函数
* @param {mars3d.Map} mapInstance 地图对象
* @returns {void} 无
*/
export function onMounted(mapInstance) {
map = mapInstance // 记录map map.toolbar.style.bottom = "55px"// 修改toolbar控件的样式
// 创建矢量数据图层
graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
graphicLayer.on(mars3d.EventType.click, function (event) {
console.log("单击了卫星", event)
// 单击事件
highlightSatellite(event.graphic)
})
graphicLayer.on(mars3d.EventType.change, function (event) {
// 位置变化事件
processInArea(event.graphic)
})
bindLayerPopup()
creatreDmzList()
mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/apidemo/tle-china.json" })
.then(function (data) {
createSatelliteList(data.data)
})
.catch(function () {
globalMsg("获取卫星信息异常!")
})
}
/**
* 释放当前地图业务的生命周期函数
* @returns {void} 无
*/
export function onUnmounted() {
map = null
}
// 创建卫星列表
function createSatelliteList(arr) {
// 单击地图空白处
map.on(mars3d.EventType.clickMap, function (event) {
highlightSatellite()
})
for (let i = 0; i < arr.length; i++) {
const item = arr[i]
// 属性处理
item.model = {
url: "//data.mars3d.cn/gltf/mars/weixin.gltf",
...(item.model || {}),
distanceDisplayCondition: true,
distanceDisplayCondition_near: 0,
distanceDisplayCondition_far: 20000000,
show: true
}
// 当视角距离超过20000000米(distanceDisplayCondition_far定义的) 后显示为点对象的样式
item.point = {
show: true,
color: "#ffff00",
pixelSize: 5,
distanceDisplayCondition: true,
distanceDisplayCondition_near: 20000000,
distanceDisplayCondition_far: Number.MAX_VALUE
}
item.label = item.label || {}
item.label.show = true
// path显示后FPS下降的厉害
item.path = item.path || {}
item.path.color = Cesium.defaultValue(item.path.color, "#e2e2e2")
item.path.closure = Cesium.defaultValue(item.path.closure, true)
item.cone = {
sensorType: i % 2 === 1 ? mars3d.graphic.SatelliteSensor.Type.Rect : mars3d.graphic.SatelliteSensor.Type.Conic,
angle1: random(20, 40),
angle2: random(10, 20),
show: false
}
// 属性处理 END
const satelliteObj = new mars3d.graphic.Satellite(item)
graphicLayer.addGraphic(satelliteObj)
}
console.log("当前卫星数量: " + arr.length)
}
// 在图层绑定Popup弹窗
export function bindLayerPopup() {
graphicLayer.bindPopup(function (event) {
const attr = event.graphic.options
return `名称:${attr.name}
英文名:${attr.name_en || ""}
类型:${attr.type}`
})
}
let lastSelectWX
function highlightSatellite(satelliteObj) {
if (lastSelectWX) {
// 重置上次选中的轨道样式
lastSelectWX.setOptions({
path: {
color: "#e2e2e2",
opacity: 0.5,
width: 1
}
})
lastSelectWX.coneShow = false // 关闭视锥体
lastSelectWX = null
}
if (satelliteObj) {
// 高亮选中的轨道样式
satelliteObj.setOptions({
path: {
color: "#ffff00",
opacity: 1,
width: 2
}
})
satelliteObj.coneShow = true // 打开视锥体
lastSelectWX = satelliteObj
}
}
// 判断卫星是否在面内
function processInArea(weixin) {
const position = weixin?.position
if (!position) {
return
}
dmzLayer.eachGraphic(function (dmzGraphic) {
if (!dmzGraphic._isFW) {
return
}
dmzGraphic._lastInPoly[weixin.uuid] = dmzGraphic._lastInPoly[weixin.uuid] || {}
const lastState = dmzGraphic._lastInPoly[weixin.uuid]
const thisIsInPoly = dmzGraphic.isInPoly(position)
if (thisIsInPoly !== lastState.state) {
if (thisIsInPoly) {
// 开始进入区域内
console.log(`${weixin.name} 卫星开始进入 ${dmzGraphic.name} 地面站区域内`)
const line = new mars3d.graphic.PolylineEntity({
positions: new Cesium.CallbackProperty(function (time) {
const pots = weixin.position
if (!pots) {
return []
}
return [pots, dmzGraphic.positionShow]
}, false),
style: {
width: 7,
// 动画线材质
material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.LineFlow, {
url: "./img/textures/arrow-h.png",
color: Cesium.Color.AQUA,
repeat: new Cesium.Cartesian2(15, 1),
speed: 60 // 时长,控制速度
}),
arcType: Cesium.ArcType.NONE
}
})
map.graphicLayer.addGraphic(line)
lastState.line = line
weixin.coneShow = true // 打开视锥体
} else {
// 离开区域
console.log(`${weixin.name} 卫星离开 ${dmzGraphic.name} 地面站区域内`)
if (lastState.line) {
map.graphicLayer.removeGraphic(lastState.line)
delete lastState.line
}
weixin.coneShow = false // 关闭视锥体
}
dmzGraphic._lastInPoly[weixin.uuid].state = thisIsInPoly
}
})
}
// 取随机数字
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
// 地面站图层
let dmzLayer
// 创建地面站
function creatreDmzList() {
const arr = [
{ name: "西安", radius: 1500000, point: [108.938314, 34.345614, 342.9] },
{ name: "喀什", radius: 1800000, point: [75.990372, 39.463507, 1249.5] },
{ name: "文昌", radius: 1200000, point: [110.755151, 19.606573, 21.1] }
]
// 创建矢量数据图层
dmzLayer = new mars3d.layer.GraphicLayer()
map.addLayer(dmzLayer)
for (let i = 0; i < arr.length; i++) {
const item = arr[i]
// 地面站gltf模型
const graphic = new mars3d.graphic.ModelEntity({
name: "地面站模型",
position: item.point,
style: {
url: "//data.mars3d.cn/gltf/mars/leida.glb",
heading: 270,
scale: 30,
minimumPixelSize: 40
},
popup: item.name
})
dmzLayer.addGraphic(graphic)
const dmfwGraphic = new mars3d.graphic.CircleEntity({
name: item.name,
position: item.point,
style: {
radius: item.radius,
color: "#ff0000",
opacity: 0.3
},
popup: item.name
})
dmzLayer.addGraphic(dmfwGraphic)
// 判断时会用到的变量
dmfwGraphic._isFW = true
dmfwGraphic._lastInPoly = {}
}
}