<template>
<div class="btn-box">
<a-button @click="start" :disabled="startDisable">start</a-button>
<br />
<a-radio-group v-model:value="optionTypeValue" class="radio">
<a-radio :value="1">手动添加</a-radio>
<a-radio :value="2">自动添加</a-radio>
</a-radio-group>
<a-row :gutter="24">
<a-col :span="12"><span> 经度: </span>
<a-input-number v-model:value="m_lng" class="input" />
</a-col>
<a-col :span="12"><span> 纬度:
<a-input-number v-model:value="m_lat" class="input" />
</span></a-col>
<a-col :span="12"><span> 高度:
<a-input-number v-model:value="m_alt" class="input" />
</span></a-col>
<a-col :span="12"><span> 间隔(s):
<a-input-number v-model:value="m_interval" class="input" />
</span></a-col>
</a-row>
<a-button @click="add" v-show="optionTypeValue === 1">添加</a-button>
</div>
<Map @onViewerLoaded="onViewerLoaded" :options="options" />
</template>
<script lang="ts" setup>
import { ref, onUnmounted } from "vue";
import { message } from 'ant-design-vue'
import * as Cesium from "cesium";
import type { Option, ViewportAndPosition } from "@/components/Cesium/typing";
import Map from "@/components/Cesium/lib/Map.vue";
import { GetPosition, Camerafly, initLayerPromise } from "@/components/Cesium/utils";
import { Helper } from "@/components/Cesium/lib/helper";
const options = ref<Option>({
orderIndependentTranslucency: false,
shouldAnimate: true,
});
let startDisable = ref(true)
let optionTypeValue = ref<number>(1)
let m_lng = ref<number>(104.063914)
let m_lat = ref<number>(30.640356)
let m_alt = ref<number>(496)
let m_interval = ref(1)
const onViewerLoaded = (viewer: Cesium.Viewer) => { //地图加载完成后的回调
initLayerPromise(viewer, true).then(() => {
const orientation = {
// heading-代表镜头左右方向,正值为右,负值为左,360度和0度是一样的
// pitch-代表镜头上下方向,正值为上,负值为下.
// roll-代表镜头左右倾斜.正值,向右倾斜,负值向左倾斜
heading: 0.0980116703834879,
pitch: -0.9951964593311571,
roll: 6.28314314123768
}
Camerafly(viewer, { lng: 104.064309, lat: 30.635843, alt: 1500 }, orientation, () => {
const getP = new GetPosition(viewer);
getP.getPositionByClick((position: ViewportAndPosition) => {
const { lng, lat, alt } = position;
m_lng.value = lng
m_lat.value = lat
m_alt.value = alt || 496
if (optionTypeValue.value === 2) add()
});
})
})
};
let index = 0 //插值经纬度索引
let maxIndex = 0// 最大插值经纬度数组索引
let pathIndex = 0// 当前经纬度数组索引
let forNum = 20 // 插值间隔
let isLookAt = false; //锁定视角
let autoDirection = true; //自动调整方向
let path: number[][] = [] //存在路线数组
let Primitive: Cesium.Primitive
let entityPath: Cesium.Entity
const hpRoll = new Cesium.HeadingPitchRoll();
let linePath: Cesium.Cartesian3[] = []
let showPath: Cesium.Cartesian3[] = [] //插值数组
let timer:NodeJS.Timer
const start = () => { //轨迹开始
const { Viewer } = window
const controller = Viewer.scene.screenSpaceCameraController;
const r =
2.0 *
Math.max((<any>Primitive).boundingSphere.radius, Viewer.camera.frustum.near);
controller.minimumZoomDistance = r * 0.5;
Viewer.scene.preUpdate.addEventListener(render)
// timer = setInterval(() => {
// render()
// }, forNum)
}
const render = (scene: Cesium.Scene, time: number) => {
// const render = () => {
if (index >= maxIndex) return
if (autoDirection && index > 0 && !showPath[index - 1].equals(showPath[index])) {
const heading = Helper.getHeading(
showPath[index - 1],
showPath[index],
);
if (heading) hpRoll.heading = heading
}
if (isLookAt) {
}
linePath.push(showPath[index])
Cesium.Transforms.headingPitchRollToFixedFrame(
showPath[index],
hpRoll,
Cesium.Ellipsoid.WGS84,
fixedFrameTransform,
Primitive.modelMatrix
);
index += 1
}
const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator("north", "west");
const initModel = () => { //初始化模型
const { Viewer } = window
let pos = Cesium.Cartesian3.fromDegrees(path[0][0], path[0][1], path[0][2])
linePath = [pos]
entityPath = Viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(() => {
return linePath;
}, false),
show: true,
material: Cesium.Color.RED,
width: 1.5,
clampToGround: true //是否贴地
}
});
Primitive = Viewer.scene.primitives.add(
Cesium.Model.fromGltf({
url: "/models/GroundVehicle.glb",
modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
pos,
hpRoll,
Cesium.Ellipsoid.WGS84,
fixedFrameTransform,
),
scale: 1,
maximumScale: 10
})
);
Primitive.readyPromise.then((model) => {
// Play and loop all animations at half-speed
(<any>model).activeAnimations.addAll({
multiplier: 0.5,
loop: Cesium.ModelAnimationLoop.REPEAT,
});
});
}
const add = () => { //添加位置点进入数组
if (m_lng.value === 0 || m_lat.value === 0) {
message.warning('经纬度不能为0')
return
}
let len = path.length - 1
if (path[len] && m_lng.value === path[len][0] && m_lat.value === path[len][1]) return
path.push([m_lng.value, m_lat.value, m_alt.value])
m_lng.value = 0
m_lat.value = 0
interpolation() //将轨迹添加进数组中
if (path.length === 1) {
initModel()
startDisable.value = false
}
}
const interpolation = () => { //插值坐标
if (path.length < 2) return
const po1 = Cesium.Cartesian3.fromDegrees(path[pathIndex][0], path[pathIndex][1], path[pathIndex][2])
const po2 = Cesium.Cartesian3.fromDegrees(path[pathIndex + 1][0], path[pathIndex + 1][1], path[pathIndex + 1][2])
getPosition(po1, po2, m_interval.value).then((res: Cesium.Cartesian3[]) => {
showPath = showPath.concat(res)
pathIndex++
maxIndex = showPath.length
})
}
const getPosition = (startP: Cesium.Cartesian3, endP: Cesium.Cartesian3, duration: number) => {
return new Promise((resolve: (value: Cesium.Cartesian3[]) => void) => {
let arr: Cesium.Cartesian3[] = []
duration = duration * 1000
for (let i = 0; i <= duration; i = i + forNum) {
let pos = Cesium.Cartesian3.lerp(startP, endP, i / duration, new Cesium.Cartesian3());
arr.push(pos)
}
if (duration % forNum !== 0) {
arr.push(endP)
}
resolve(arr);
})
}
onUnmounted(() => {
// timer && clearInterval(timer)
const { Viewer } = window;
(Viewer as Cesium.Viewer).scene.preUpdate.removeEventListener(render)
})
</script>
<style lang="less" scoped>
.btn-box {
position: absolute;
top: 10px;
z-index: 10;
width: 500px;
margin-left: 20px;
background-color: rgba(0, 0, 0, .7);
color: #fff;
padding: 10px;
.input {
width: 120px;
margin-right: 5px;
}
.radio {
.ant-radio-wrapper {
color: #
评论4