说明:
- cesium环境我就不多说了,不知道可以看看我其他文章
- 准备一个模型,文章中用了一个无人机模型(
modelNew.gltf
)
代码
直接上代码了,记得自己创建三维球(viewer)
// 坐标点集合
const positions = [
{
x: 106.6508791624685,
y: 38.2070065411105,
},
{
x: 106.65084448321753,
y: 38.20701316684506,
},
{
x: 106.65081837459833,
y: 38.20702957797115,
},
{
x: 106.65080407607039,
y: 38.20705012580083,
},
{
x: 106.65078146477492,
y: 38.20707176680645,
},
{
x: 106.650787140095,
y: 38.207098627516125,
},
{
x: 106.65079479861747,
y: 38.20712541619226,
},
{
x: 106.65080548387834,
y: 38.20714418928443,
},
{
x: 106.65082842992122,
y: 38.207157308537575,
},
{
x: 106.65086015327147,
y: 38.2071646326481,
},
{
x: 106.65089329863535,
y: 38.20716712294016,
},
{
x: 106.65092965997819,
y: 38.20715950506601,
},
{
x: 106.65094600304977,
y: 38.2071511175259,
},
{
x: 106.65096440238267,
y: 38.20714335913305,
},
{
x: 106.65097872313838,
y: 38.20712728477713,
},
{
x: 106.65098722414237,
y: 38.20711248230986,
},
{
x: 106.65098902379766,
y: 38.2070958864103,
},
{
x: 106.65098902379766,
y: 38.2070958864103,
},
{
x: 106.65098901240313,
y: 38.20706931460631,
},
{
x: 106.65098035570837,
y: 38.20704856857603,
},
{
x: 106.65096704126798,
y: 38.20703368257398,
},
{
x: 106.65095023082833,
y: 38.20701832778473,
},
];
// 漫游
const startRoam = () => {
// 飞到对应的视角
viewer.camera.flyTo({
destination: {
x: -1437916.6278362537,
y: 4807890.070128957,
z: 3923547.9763706536,
},
orientation: {
heading: 0.8271405261220597,
pitch: -0.7266629636851301,
roll: 6.868864934617136e-7,
},
});
// 创建采样位置属性
const positionProperty = new Cesium.SampledPositionProperty();
positionProperty.setInterpolationOptions({
interpolationAlgorithm: Cesium.LinearApproximation,
interpolationDegree: 1, // 线性插值对应的次数是 1
});
// 设置时间范围(30秒动画)
const startTime = Cesium.JulianDate.fromDate(new Date());
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
30,
new Cesium.JulianDate()
);
// 设置时钟
viewer.clock.startTime = startTime.clone();
viewer.clock.stopTime = stopTime.clone();
viewer.clock.currentTime = startTime.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 只执行一次,到达结束时间后停止 Cesium.ClockRange.LOOP_STOP; 循环执行
viewer.clock.multiplier = 1; // 播放速度
viewer.clock.shouldAnimate = true; // 启动时钟
// 添加路径点(沿曲线飞行)
for (let i = 0; i < positions.length; i++) {
const time = Cesium.JulianDate.addSeconds(
startTime,
i,
new Cesium.JulianDate()
);
const position = Cesium.Cartesian3.fromDegrees(
positions[i].x, // 经度随时间增加
positions[i].y, // 纬度随时间波动
30 // 高度随时间增加
);
positionProperty.addSample(time, position);
}
// 创建实体并添加平滑移动
const entity = viewer.entities.add({
position: positionProperty,
model: {
// 引入模型
uri: "/modelNew.gltf",
// 模型的近似最小像素大小,而不考虑缩放。这可以用来确保即使观看者缩小也可以看到模型。如果为0.0,则不强制使用最小大小
minimumPixelSize: 12,
// 模型的颜色(与模型的渲染颜色混合的属性)
// color: Cesium.Color.WHITE.withAlpha(1),
// 模型的最大比例大小
maximumScale: 1,
// 是否执行模型动画
runAnimations: true,
// 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。
scale: 0.05,
// 显示在距相机的距离处的属性,多少区间内是可以显示的
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0,
1500
),
// 是否显示
show: true,
},
path: {
resolution: 1,
material: Cesium.Color.WHITE.withAlpha(0.5),
width: 7,
leadTime: 0, // 不显示未来路径
trailTime: 30, // 显示过去30秒的路径
}
});
viewer.clock.onTick.addEventListener(() => {
console.log("当前时间:", viewer.clock.currentTime);
console.log(
"模型位置:",
entity.position.getValue(viewer.clock.currentTime)
);
});
viewer.clock.onTick.addEventListener(() => {
if (
Cesium.JulianDate.equals(
viewer.clock.currentTime,
viewer.clock.stopTime
)
) {
console.log("动画已结束,清除轨迹");
// 方法 1:直接移除 path 属性
entity.path = undefined;
}
});
};
效果图: