前言
飞行的主要实现思路是通过轨迹点计算空中飞行距离,然后计算每段匀速飞行的时间,当然你也可以变速。本文就是匀速飞行的实现,希望能对你有所帮助。
数据制作可参考《使用QGIS制作航线数据,用Cesium加载查看》
代码实现参考文章
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link href="../../Cesium/Widgets/widgets.css" rel="stylesheet">
<script type="text/javascript" src="../../Cesium/Cesium.js"></script>
<title>飞行</title>
</head>
<body style="margin: 0px;width:100%;height:100%;">
<div id="cesiumContainer" style="width:100%;height:100%;position:absolute;"></div>
<div style="top:10px;left:10px;position:absolute;">
<div style="background: #fff;padding:10px;" id="play">飞行</div>
<div style="background: #fff;padding:10px;" id="pause">暂停</div>
<div style="background: #fff;padding:10px;" id="time">设置当前时间</div>
</div>
</body>
<script>
//created by onegiser at 2021-10-30
const key='天地图key'
const viewer = new Cesium.Viewer('cesiumContainer', {
imageryProviderViewModels: [
new Cesium.ProviderViewModel({
name: "天地图影像",
iconUrl: "/imgs/map/tdt_img.jpg",
tooltip: "",
creationFunction: () => {
const imgImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: "http://t{s}.tianditu.com/img_c/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" + key,
subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
tilingScheme: new Cesium.GeographicTilingScheme(),
tileMatrixLabels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"]
})
return [imgImageryProvider]
}
}),
]
})
let inter, entity, start, stop
//飞行数据
const flyDatas = {
"properties": {
"id": "fad07e10-1854-11ec-90a2-97310cdff148"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
84.26606989058006,
28.893720619299657,
6518.704454870537
],
[
84.5499583941043,
28.75363498215204,
6036.864577931667
],
[
84.92774603698726,
28.572093371042484,
4776.540165893245
],
[
85.57643103471693,
28.310271180323234,
5333.176522423159
]
]
}
}
const createPosition = (datas, time, height) => {
let totalDistance = 0//总的距离
const distances = []
const positions = []
const times = []
const property = new Cesium.SampledPositionProperty()
if (datas) {
for (let i in datas.geometry.coordinates) {
const coordinates = datas.geometry.coordinates[i]
const position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], height ? height : coordinates[2])
positions.push(position)
if (Number(i) === 0) {
} else {
const lastPosition = positions[Number(i) - 1]
const geoPositions = [Cesium.Ellipsoid.WGS84.cartesianToCartographic(lastPosition), Cesium.Ellipsoid.WGS84.cartesianToCartographic(position)]
const ellipsoidGeodesic = new Cesium.EllipsoidGeodesic(geoPositions[0], geoPositions[1])
const distance = ellipsoidGeodesic.surfaceDistance//表面距离
distances.push(distance)
totalDistance += distance
}
}
const speed = totalDistance / time
let start, stop
for (let i in positions) {
const position = positions[i]
if (Number(i) === 0) {
start = Cesium.JulianDate.now()
// stop = Cesium.JulianDate.addSeconds(start, time, new Cesium.JulianDate())
property.addSample(start, position)
times.push(start.clone())
} else {
const _time = distances[Number(i) - 1] / speed//根据速度计算本线段的时间
const tempTime = Cesium.JulianDate.addSeconds(times[Number(i) - 1], _time, new Cesium.JulianDate())
times.push(tempTime)
property.addSample(tempTime, position)
}
}
}
return { property, times, totalDistance }
}
const viewFly = (viewer, datas) => {
const id = "router-fly-line"
const time = 60
const { property, times, totalDistance } = createPosition(datas, time)
if (times && times.length > 1) {
start = times[0]
stop = times[times.length - 1]
const availability = new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start,
stop
})])
const entityOption = {
id,
name: id,
availability,
position: property,
orientation: new Cesium.VelocityOrientationProperty(property),
}
const model = {
show: true,
uri: "/imgs/models/feiji.glb",
scale: 1,
minimumPixelSize: 100,
heightReference: Cesium.HeightReference.NONE,
}
entityOption.model = model
entity = viewer.entities.add(entityOption)
viewer.clock.startTime = start.clone()
viewer.clock.currentTime = start.clone()
viewer.clock.stopTime = stop.clone()
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED
viewer.clock.shouldAnimate = false
}
}
function setClockCurrentTime(time) {
viewer.clock.currentTime = Cesium.JulianDate.addSeconds(start, time, new Cesium.JulianDate())
}
viewFly(viewer, flyDatas)
let t = 0
function interFun() {
inter = setInterval(() => {
t++
console.log(t)
if (t === 1) {
console.log(viewer.camera)
}
if (t === 30) {
console.log(viewer.camera)
}
}, 1000)
}
function setViewer() {
viewer.scene.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(84.26606989058006,
28.893720619299657,
20000), // 点的坐标
orientation: {
heading: 6.273949775088365,
pitch: -0.7857772222180337,
roll: 6.283148089310608,
}
})
}
document.getElementById("play").onclick = () => {
viewer.trackedEntity = entity
setTimeout(()=>{
setViewer()
},5000)
viewer.clock.shouldAnimate = true
interFun()
}
document.getElementById("pause").onclick = () => {
viewer.clock.shouldAnimate = false
if (inter) {
clearInterval(inter)
}
}
document.getElementById("time").onclick = () => {
setClockCurrentTime(30)
}
</script>
</html>