效果:
实现思路(最后有完整代码):
1.用clock组件创建时间线
2.时间轴和飞机的位置信息绑定
3.添加模型让模型按照绑定的位置飞行
4.创建粒子系统就是飞机的两个喷口
粒子所需图片地址链接:https://pan.baidu.com/s/12fUyDn6M_uyna5bGHTOvSQ
提取码:1234
5.让粒子实时跟随模型移动
1.用clock组件创建时间线 代码:
// 创建时间线
var start = Cesium.JulianDate.fromDate(new Date()); // 设置时间轴当前时间为开始时间
var start = Cesium.JulianDate.addHours(start, 8, new Cesium.JulianDate()); // 开始时间加8小时改为北京时间
var stop = Cesium.JulianDate.addSeconds(start, 400, new Cesium.JulianDate()); // 设置结束时间为开始时间加400秒
// 设置时钟开始时间
viewer.clock.startTime = start.clone();
// 设置时钟当前时间
viewer.clock.currentTime = start.clone();
// 设置时钟结束时间
viewer.clock.stopTime = stop.clone();
// 时间速率,数字越大时间过的越快,设置1好像是和实际时间一样
viewer.clock.multiplier = 0.8;
// 时间轴绑定到viewer上去
// viewer.timeline.zoomTo(start, stop);
// 循环执行,到达终止时间,重新从起点时间开始
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
2.时间轴和飞机的位置信息绑定 代码:
//设置飞行轨迹
var data = [
{
long: 111.110693,
lat: 36.0994841,
height: 10000,
time: 0,
},
{
long: 111.112693,
lat: 35.0994841,
height: 10000,
time: 180,
},
{
longe: 112.310693,
lat: 34.0994841,
height: 50000,
time: 400,
},
];
let property = computeFlight(data); // 这是通过一个方法把时间轴和飞机的位置信息绑定了
// 时间轴和飞机的位置信息绑定
function computeFlight(source) {
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < source.length; i++) {
let time = Cesium.JulianDate.addSeconds(
start,
source[i].time,
new Cesium.JulianDate()
);
let position = Cesium.Cartesian3.fromDegrees(
source[i].long,
source[i].lat,
source[i].height
);
// 添加位置,和时间对应
property.addSample(time, position);
}
return property;
}
3.添加模型让模型按照绑定的位置飞行 代码:
// 添加并移动飞机
var entity2 = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
]),
position: property,
// 基于位置计算方向角
orientation: new Cesium.VelocityOrientationProperty(property),
model: {
uri: "./model/j11.gltf",
scale: 100.05, //放大倍数
},
// 画出飞行路径
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1, // 颜色透明度
color: Cesium.Color.fromCssColorString("rgba(0, 253, 239, 0.5)"), // 路线颜色
}),
width: 2, // 路线的显示宽度
},
});
// 视角跟随模型
viewer.trackedEntity = entity2;
4.创建粒子系统就是飞机的两个喷口火焰效果
因为后面要更新粒子的位置 所以先搞个变量接一下 代码:
可以通过emitter给粒子设置不同样式
这里需要给粒子设置基于模型的位置偏移 不然粒子会在模型中心置 computeEmitterModelMatrix函数中设置
// emitter: new Cesium.CircleEmitter(0.5), //粒子发射器样式 圆形
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形
// emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形
// emitter: new Cesium.SphereEmitter(0.5), //球形
// 会有两个粒子 一个左喷口一个右喷口
let particleSystemaArr = [];
particleSystemaArr[0] = particleSystema(-932.5, -103.5, 201.0);
particleSystemaArr[1] = particleSystema(-932.5, 103.5, 201.0);
// 创建粒子系统 这个是最重要部分
function particleSystema(z, x, y) {
var particle;
particle = viewer.scene.primitives.add(
new Cesium.ParticleSystem({
image: "./imgs/fire3.png",
startScale: 70, //粒子图像的初始比例
endScale: 80, //粒子图像的结束比例
// lifetime: 1.0, //粒子系统发射粒子的时间(以秒为单位)。
emissionRate: 55, //每秒要发射的粒子数
//主模型参数(位置)
// 发射器参数
// emitter: new Cesium.CircleEmitter(0.5), //粒子发射器样式 圆形
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形
// emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形
// emitter: new Cesium.SphereEmitter(0.5), //球形
speed: 1,
minimumParticleLife: 0.1, //粒子生命的可能持续时间的最小范围
maximumParticleLife: 0.4, //粒子生命的可能持续时间的最大范围
//颜色
startColor: Cesium.Color.RED.withAlpha(0.7), //粒子在其生命初期的颜色
endColor: Cesium.Color.YELLOW.withAlpha(0.5), //粒子在其生命结束的颜色
modelMatrix: computeModelMatrix(entity2, Cesium.JulianDate.now()), //从模型转换为世界坐标的4x4转换矩阵
emitterModelMatrix: computeEmitterModelMatrix(z, x, y), // 粒子发射器模型矩阵,粒子发射器位置
})
);
return particle;
}
// 计算当前时间点飞机模型的位置矩阵
function computeModelMatrix(entity, time) {
//获取位置
var position = Cesium.Property.getValueOrUndefined(
entity2.position,
time,
new Cesium.Cartesian3()
);
if (!Cesium.defined(position)) {
return undefined;
}
//获取方向
var modelMatrix;
var orientation = Cesium.Property.getValueOrUndefined(
entity.orientation,
time,
new Cesium.Quaternion()
);
if (!Cesium.defined(orientation)) {
modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
position,
undefined,
new Cesium.Matrix4()
);
} else {
modelMatrix = Cesium.Matrix4.fromRotationTranslation(
Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()),
position,
new Cesium.Matrix4()
);
}
return modelMatrix;
}
// 粒子发射器位置
function computeEmitterModelMatrix(x, y, z) {
//方向
var hpr = Cesium.HeadingPitchRoll.fromDegrees(
0.0,
0.0,
0.0,
new Cesium.HeadingPitchRoll()
);
var trs = new Cesium.TranslationRotationScale();
//以modelMatrix(飞机模型)中心为原点的坐标系的xyz轴位置偏移
trs.translation = Cesium.Cartesian3.fromElements(
x,
y,
z,
new Cesium.Cartesian3()
);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(
hpr,
new Cesium.Quaternion()
);
return Cesium.Matrix4.fromTranslationRotationScale(
trs,
new Cesium.Matrix4()
);
}
5.让粒子实时跟随模型移动 代码:
// 粒子跟随模型
viewer.scene.preRender.addEventListener(function (scene, time) {
//重新计算位置
particleSystemaArr[0].modelMatrix = computeModelMatrix(entity2, time);
particleSystemaArr[1].modelMatrix = computeModelMatrix(entity2, time);
});
全部完整代码: