模型动画效果
时钟设置
vue
<template>
<div id="cesiumContainer"></div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "cesium/Build/Cesium/Widgets/widgets.css"
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGM1ODNmMi01NjgxLTRiNjYtYjEzYS0xMWZhODZlNDIyOWIiLCJpZCI6MTE2MzEzLCJpYXQiOjE3MzY2NjMwNjN9.tTeB32oDNJyNSn7iecCvMb2O5ETRw56CmX_OCSsMu34"
let viewer: Cesium.Viewer
onMounted(() => {
initMap()
})
async function initMap() {
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
// 不设置该属性,模型的动画不会显示
shouldAnimate: true,
terrainProvider: await Cesium.createWorldTerrainAsync({
requestWaterMask: true,
requestVertexNormals: true
})
})
/** 时钟设置 */
const startTime = Cesium.JulianDate.fromDate(new Date(2025, 2, 16, 17, 0, 0))
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
360,
new Cesium.JulianDate()
)
viewer.clock.startTime = startTime.clone()
viewer.clock.stopTime = stopTime.clone()
viewer.clock.multiplier = 20 // 时钟速度调为正常的 20 倍
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 开启时钟动画,循环播放
viewer.timeline.zoomTo(startTime, stopTime) // 时间轴固定到指定范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.541, 37.815, 20000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
}
</script>
Entity实体加载与路线绘制
vue
<template>
<div id="cesiumContainer"></div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "cesium/Build/Cesium/Widgets/widgets.css"
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGM1ODNmMi01NjgxLTRiNjYtYjEzYS0xMWZhODZlNDIyOWIiLCJpZCI6MTE2MzEzLCJpYXQiOjE3MzY2NjMwNjN9.tTeB32oDNJyNSn7iecCvMb2O5ETRw56CmX_OCSsMu34"
let viewer: Cesium.Viewer
let planeModel: Cesium.Entity
let positionProperty: Cesium.SampledPositionProperty
onMounted(() => {
initMap()
})
async function initMap() {
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
// 不设置该属性,模型的动画不会显示
shouldAnimate: true,
terrainProvider: await Cesium.createWorldTerrainAsync({
requestWaterMask: true,
requestVertexNormals: true
})
})
/** 时钟设置 */
// Cesium.JulianDate.now()可以获取当前时间
const startTime = Cesium.JulianDate.fromDate(new Date(2025, 2, 16, 17, 0, 0))
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
360,
new Cesium.JulianDate()
)
viewer.clock.startTime = startTime.clone()
viewer.clock.stopTime = stopTime.clone()
viewer.clock.multiplier = 20 // 时钟速度调为正常的 20 倍
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 开启时钟动画,循环播放
viewer.timeline.zoomTo(startTime, stopTime) // 时间轴固定到指定范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.541, 37.815, 20000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
/** Entity实体加载与线路绘制 */
const dataPoints = [
{ longitude: -122.567, latitude: 37.843, height: 200 },
{ longitude: -122.537, latitude: 37.817, height: 500 },
{ longitude: -122.519, latitude: 37.811, height: 800 },
{ longitude: -122.475, latitude: 37.822, height: 500 },
{ longitude: -122.464, latitude: 37.854, height: 300 },
{ longitude: -122.438, latitude: 37.874, height: 500 }
]
positionProperty = new Cesium.SampledPositionProperty()
for (let i = 0; i < dataPoints.length; i++) {
const time = Cesium.JulianDate.addSeconds(startTime, i * 72, new Cesium.JulianDate())
const position = Cesium.Cartesian3.fromDegrees(
dataPoints[i].longitude,
dataPoints[i].latitude
)
// 用于创建具有时间依赖性的位置点动画
positionProperty.addSample(time, position)
// 将每一个点添加到地图中
viewer.entities.add({
position: position,
point: {
show: true,
pixelSize: 8,
color: Cesium.Color.TRANSPARENT,
outlineColor: Cesium.Color.ORANGE,
outlineWidth: 3
}
})
}
</script>
飞机模型加载
vue
<template>
<div id="cesiumContainer"></div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "cesium/Build/Cesium/Widgets/widgets.css"
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGM1ODNmMi01NjgxLTRiNjYtYjEzYS0xMWZhODZlNDIyOWIiLCJpZCI6MTE2MzEzLCJpYXQiOjE3MzY2NjMwNjN9.tTeB32oDNJyNSn7iecCvMb2O5ETRw56CmX_OCSsMu34"
let viewer: Cesium.Viewer
let planeModel: Cesium.Entity
let positionProperty: Cesium.SampledPositionProperty
onMounted(() => {
initMap()
})
async function initMap() {
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
// 不设置该属性,模型的动画不会显示
shouldAnimate: true,
terrainProvider: await Cesium.createWorldTerrainAsync({
requestWaterMask: true,
requestVertexNormals: true
})
})
/** 时钟设置 */
// Cesium.JulianDate.now()可以获取当前时间
const startTime = Cesium.JulianDate.fromDate(new Date(2025, 2, 16, 17, 0, 0))
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
360,
new Cesium.JulianDate()
)
viewer.clock.startTime = startTime.clone()
viewer.clock.stopTime = stopTime.clone()
viewer.clock.multiplier = 20 // 时钟速度调为正常的 20 倍
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 开启时钟动画,循环播放
viewer.timeline.zoomTo(startTime, stopTime) // 时间轴固定到指定范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.541, 37.815, 20000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
/** Entity实体加载与线路绘制 */
const dataPoints = [
{ longitude: -122.567, latitude: 37.843, height: 200 },
{ longitude: -122.537, latitude: 37.817, height: 500 },
{ longitude: -122.519, latitude: 37.811, height: 800 },
{ longitude: -122.475, latitude: 37.822, height: 500 },
{ longitude: -122.464, latitude: 37.854, height: 300 },
{ longitude: -122.438, latitude: 37.874, height: 500 }
]
positionProperty = new Cesium.SampledPositionProperty()
for (let i = 0; i < dataPoints.length; i++) {
const time = Cesium.JulianDate.addSeconds(
startTime,
i * 72,
new Cesium.JulianDate()
)
const position = Cesium.Cartesian3.fromDegrees(
dataPoints[i].longitude,
dataPoints[i].latitude
)
// 用于创建具有时间依赖性的位置点动画
positionProperty.addSample(time, position)
// 将每一个点添加到地图中
viewer.entities.add({
position: position,
point: {
show: true,
pixelSize: 8,
color: Cesium.Color.TRANSPARENT,
outlineColor: Cesium.Color.ORANGE,
outlineWidth: 3
}
})
}
/** 飞机模型加载 */
planeModel = viewer.entities.add({
id: "plane-408",
name: "plane-408-无人机",
// availability属性用于控制实体在时间轴上的有效性,它允许你指定实体在特定的时间段内才可见。
// 如果不指定 availability 属性,则实体会在整个事件范围内可见。
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: startTime,
stop: stopTime
})
]),
// Cesium.VelocityOrientationProperty 用于根据实体的速度自动计算和更新其朝向。
// 它基于实体的运动方向来确定朝向,使得实体能够在移动时保持正确的朝向。
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
position: positionProperty,
model: {
scale: 10,
uri: "/model/Cesium/Cesium_Air.glb",
minimumPixelSize: 64
},
path: {
resolution: 1,
width: 15,
material: new Cesium.PolylineGlowMaterialProperty({
// 发光的强度
glowPower: 0.1,
// path路径的渐缩效果,1.0或不设置代表不会设置渐缩效果
taperPower: 1.0,
color: Cesium.Color.ORANGE
})
}
})
}
</script>
视角切换
vue
<template>
<div id="cesiumContainer">
<div id="buttonGroup">
<button @click="changeView('down')">俯视视图</button>
<button @click="changeView('entity')">实体视图</button>
<button @click="changeView('side')">侧面视图</button>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "cesium/Build/Cesium/Widgets/widgets.css"
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGM1ODNmMi01NjgxLTRiNjYtYjEzYS0xMWZhODZlNDIyOWIiLCJpZCI6MTE2MzEzLCJpYXQiOjE3MzY2NjMwNjN9.tTeB32oDNJyNSn7iecCvMb2O5ETRw56CmX_OCSsMu34"
let viewer: Cesium.Viewer
let planeModel: Cesium.Entity
let positionProperty: Cesium.SampledPositionProperty
onMounted(() => {
initMap()
})
async function initMap() {
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
// 不设置该属性,模型的动画不会显示
shouldAnimate: true,
terrainProvider: await Cesium.createWorldTerrainAsync({
requestWaterMask: true,
requestVertexNormals: true
})
})
/** 时钟设置 */
// Cesium.JulianDate.now()可以获取当前时间
const startTime = Cesium.JulianDate.fromDate(new Date(2025, 2, 16, 17, 0, 0))
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
360,
new Cesium.JulianDate()
)
viewer.clock.startTime = startTime.clone()
viewer.clock.stopTime = stopTime.clone()
viewer.clock.multiplier = 20 // 时钟速度调为正常的 20 倍
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 开启时钟动画,循环播放
viewer.timeline.zoomTo(startTime, stopTime) // 时间轴固定到指定范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.541, 37.815, 20000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
/** Entity实体加载与线路绘制 */
const dataPoints = [
{ longitude: -122.567, latitude: 37.843, height: 200 },
{ longitude: -122.537, latitude: 37.817, height: 500 },
{ longitude: -122.519, latitude: 37.811, height: 800 },
{ longitude: -122.475, latitude: 37.822, height: 500 },
{ longitude: -122.464, latitude: 37.854, height: 300 },
{ longitude: -122.438, latitude: 37.874, height: 500 }
]
positionProperty = new Cesium.SampledPositionProperty()
for (let i = 0; i < dataPoints.length; i++) {
const time = Cesium.JulianDate.addSeconds(
startTime,
i * 72,
new Cesium.JulianDate()
)
const position = Cesium.Cartesian3.fromDegrees(
dataPoints[i].longitude,
dataPoints[i].latitude
)
// 用于创建具有时间依赖性的位置点动画
positionProperty.addSample(time, position)
// 将每一个点添加到地图中
viewer.entities.add({
position: position,
point: {
show: true,
pixelSize: 8,
color: Cesium.Color.TRANSPARENT,
outlineColor: Cesium.Color.ORANGE,
outlineWidth: 3
}
})
}
/** 飞机模型加载 */
planeModel = viewer.entities.add({
id: "plane-408",
name: "plane-408-无人机",
// availability属性用于控制实体在时间轴上的有效性,它允许你指定实体在特定的时间段内才可见。
// 如果不指定 availability 属性,则实体会在整个事件范围内可见。
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: startTime,
stop: stopTime
})
]),
// Cesium.VelocityOrientationProperty 用于根据实体的速度自动计算和更新其朝向。
// 它基于实体的运动方向来确定朝向,使得实体能够在移动时保持正确的朝向。
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
position: positionProperty,
model: {
scale: 10,
uri: "/model/Cesium/Cesium_Air.glb",
minimumPixelSize: 64
},
path: {
resolution: 1,
width: 15,
material: new Cesium.PolylineGlowMaterialProperty({
// 发光的强度
glowPower: 0.1,
// path路径的渐缩效果,1.0或不设置代表不会设置渐缩效果
taperPower: 1.0,
color: Cesium.Color.ORANGE
})
}
})
}
function changeView(type: string) {
switch (type) {
case "down":
viewer.zoomTo(
viewer.entities,
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90))
)
break
case "entity":
viewer.trackedEntity = planeModel
break
case "side":
viewer.zoomTo(
planeModel,
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-30), 4000)
)
break
default:
break
}
}
</script>
<style scoped>
#buttonGroup {
position: absolute;
top: 10px;
left: 10px;
z-index: 9999;
}
#buttonGroup button {
margin-right: 8px;
}
</style>
路径过渡效果
vue
<template>
<div id="cesiumContainer">
<div id="buttonGroup">
<button @click="changeView('down')">俯视视图</button>
<button @click="changeView('entity')">实体视图</button>
<button @click="changeView('side')">侧面视图</button>
</div>
<div id="selectGroup">
<select @change="handleSelect">
<option value="line">线性近似插值路径</option>
<option value="hermite">二次赫米尔多项式近似插值路径</option>
<option value="lagrange">拉格朗日多项式近似插值路径</option>
</select>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "cesium/Build/Cesium/Widgets/widgets.css"
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGM1ODNmMi01NjgxLTRiNjYtYjEzYS0xMWZhODZlNDIyOWIiLCJpZCI6MTE2MzEzLCJpYXQiOjE3MzY2NjMwNjN9.tTeB32oDNJyNSn7iecCvMb2O5ETRw56CmX_OCSsMu34"
let viewer: Cesium.Viewer
let planeModel: Cesium.Entity
let positionProperty: Cesium.SampledPositionProperty
onMounted(() => {
initMap()
})
async function initMap() {
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
// 不设置该属性,模型的动画不会显示
shouldAnimate: true,
terrainProvider: await Cesium.createWorldTerrainAsync({
requestWaterMask: true,
requestVertexNormals: true
})
})
/** 时钟设置 */
// Cesium.JulianDate.now()可以获取当前时间
const startTime = Cesium.JulianDate.fromDate(new Date(2025, 2, 16, 17, 0, 0))
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
360,
new Cesium.JulianDate()
)
viewer.clock.startTime = startTime.clone()
viewer.clock.stopTime = stopTime.clone()
viewer.clock.multiplier = 20 // 时钟速度调为正常的 20 倍
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 开启时钟动画,循环播放
viewer.timeline.zoomTo(startTime, stopTime) // 时间轴固定到指定范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.541, 37.815, 20000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
/** Entity实体加载与线路绘制 */
const dataPoints = [
{ longitude: -122.567, latitude: 37.843, height: 200 },
{ longitude: -122.537, latitude: 37.817, height: 500 },
{ longitude: -122.519, latitude: 37.811, height: 800 },
{ longitude: -122.475, latitude: 37.822, height: 500 },
{ longitude: -122.464, latitude: 37.854, height: 300 },
{ longitude: -122.438, latitude: 37.874, height: 500 }
]
positionProperty = new Cesium.SampledPositionProperty()
for (let i = 0; i < dataPoints.length; i++) {
const time = Cesium.JulianDate.addSeconds(
startTime,
i * 72,
new Cesium.JulianDate()
)
const position = Cesium.Cartesian3.fromDegrees(
dataPoints[i].longitude,
dataPoints[i].latitude
)
// 用于创建具有时间依赖性的位置点动画
positionProperty.addSample(time, position)
// 将每一个点添加到地图中
viewer.entities.add({
position: position,
point: {
show: true,
pixelSize: 8,
color: Cesium.Color.TRANSPARENT,
outlineColor: Cesium.Color.ORANGE,
outlineWidth: 3
}
})
}
/** 飞机模型加载 */
planeModel = viewer.entities.add({
id: "plane-408",
name: "plane-408-无人机",
// availability属性用于控制实体在时间轴上的有效性,它允许你指定实体在特定的时间段内才可见。
// 如果不指定 availability 属性,则实体会在整个事件范围内可见。
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: startTime,
stop: stopTime
})
]),
// Cesium.VelocityOrientationProperty 用于根据实体的速度自动计算和更新其朝向。
// 它基于实体的运动方向来确定朝向,使得实体能够在移动时保持正确的朝向。
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
position: positionProperty,
model: {
scale: 10,
uri: "/model/Cesium/Cesium_Air.glb",
minimumPixelSize: 64
},
path: {
resolution: 1,
width: 15,
material: new Cesium.PolylineGlowMaterialProperty({
// 发光的强度
glowPower: 0.1,
// path路径的渐缩效果,1.0或不设置代表不会设置渐缩效果
taperPower: 1.0,
color: Cesium.Color.ORANGE
})
}
})
}
function changeView(type: string) {
switch (type) {
case "down":
viewer.zoomTo(
viewer.entities,
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90))
)
break
case "entity":
viewer.trackedEntity = planeModel
break
case "side":
viewer.zoomTo(
planeModel,
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-30), 4000)
)
break
default:
break
}
}
function handleSelect(e: any) {
switch (e.target.value) {
case "hermite":
positionProperty.setInterpolationOptions({
interpolationDegree: 2, // 二次赫米尔多项式插值
interpolationAlgorithm: Cesium.HermitePolynomialApproximation
})
planeModel.position = positionProperty
break
case "lagrange":
positionProperty.setInterpolationOptions({
interpolationDegree: 5, // 五次拉格朗日多项式插值
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
})
break
case "line":
default:
positionProperty.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation
})
planeModel.position = positionProperty
break
}
}
</script>
<style scoped>
#buttonGroup {
position: absolute;
top: 10px;
left: 10px;
z-index: 9999;
}
#buttonGroup button {
margin-right: 8px;
}
#selectGroup {
position: absolute;
top: 40px;
left: 10px;
z-index: 9999;
}
</style>