在近期的一个项目中要实现 根据后台数据生成轨迹动画,但是后台返回的数据在拐角处非常生硬,如下图
动画在拐角的地方会突然变化方向,想要实现动画平滑的拐角,想要后台完善数据是不可能的了,只能自己想办法,查了很多资料,推荐使用创建插值的方法。在Cesium官网中介绍了3中插值的使用方式,分别是:LinearApproximation、LagrangePolynomialApproximation、HermitePolynomialApproximation,相应的代码如下:
// LinearApproximation
entity.position.setInterpolationOptions({
interpolationDegree : 1,
interpolationAlgorithm : Cesium.LinearApproximation
});
// LagrangePolynomialApproximation
entity.position.setInterpolationOptions({
interpolationDegree : 5,
interpolationAlgorithm : Cesium.LagrangePolynomialApproximation
});
// HermitePolynomialApproximation
entity.position.setInterpolationOptions({
interpolationDegree : 2,
interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});
其中interpolationDegree数值越大,插值数越多。知识点说完了,以下是平滑动画实现的全部过程
1、从后台获取轨迹数据
// 查询路线
this.$get(false, '后台接口地址', '参数').then((res) => {
if (!res.isError && res.data.length > 0) {
const { data } = res;
const polylineCollection = new Cesium.PolylineCollection();
// 合成轨迹数据
for (let t = 0, l = data.length; t < l; t++) {
let path = [];
data[t].TRACK.forEach((v) => {
path.push(v.mapX * 1);
path.push(v.mapY * 1);
path.push(3); //设定一个默认的高程
});
// 折现集合
polylineCollection.add({
positions: Cesium.Cartesian3.fromDegreesArrayHeights(path),
});
}
// 生成动画
that.creatAnimat(polylineCollection._polylines[0])
} else {
this.$message.error('没有查询到巡更轨迹');
}
});
2、生成动画
// 创建动画
creatAnimat(line) {
let modelUrl = '模型路径';
let timeRate = 300; // 动画的时间
viewer.clock.canAnimate = true;
viewer.clock._shouldAnimate = true;
const { length } = line._positions;
const start = Cesium.JulianDate.fromDate(new Date());
const stop = Cesium.JulianDate.addSeconds(start, length * timeRate, new Cesium.JulianDate());
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 1;
const position = this.computeCirclularFlight(line, start, stop);
this.nodeAnimationModel = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start,
stop,
})]),
position,
path:{
show: true,
width: 3,
material: Cesium.Color.fromCssColorString('#03B24C'),
},
point:{
pixelSize: 5,
show: true, // 不能设为false
},
orientation: new Cesium.VelocityOrientationProperty(position),
model: {
uri: modelUrl,
minimumPixelSize: 50,
maximumScale: 100,
},
});
},
3、计算轨迹,在这里设置了插值
// 计算轨迹
computeCirclularFlight(line, start) {
const { length } = line._positions;
const property = new Cesium.SampledPositionProperty();
// 设置平滑轨迹(利用插值实现)
property.setInterpolationOptions({
interpolationDegree: 2, //值越大,越平滑,拐角越趋向圆形
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
});
let sum = 0;
let distance;
for (let i = 0; i < length; i++) {
const pos = line._positions[i];
if (i > 0) {
const prepostion = line._positions[i - 1];
distance = Cesium.Cartesian3.distance(pos, prepostion);
}
sum += distance || 0;
const time = Cesium.JulianDate.addSeconds(start, sum / 20, new Cesium.JulianDate());
if (i === length - 1) {
viewer.clock.stopTime = time;
}
property.addSample(time, pos);
}
return property;
},
最终效果