**最近项目有个需求需要实现轨迹回放组件的封装,要求轨迹线颜色可配置,轨迹回放速度可调,移动物体可配置,能够获取轨迹进度,拖动轨迹进度实现轨迹移动等等需求**
轨迹组件类
import { point as pointHelper, lineString as lineHelper, featureCollection as featureHelper } from '@turf/helpers'
import bearing from '@turf/bearing'
import lineLength from '@turf/length'
import along from '@turf/along'
import midpoint from '@turf/midpoint'
/**
* 轨迹回放专题图类(基于 mapbox原生 + turf)
*/
export class TrackPlaybackMap {
// 动画对象ID
private animateId = 0;
// 动态轨迹函数
private animateFunction: any;
// 轨迹运行状态
private animateStatus = '';
// 初始航线 未打散
private line: any;
// 打散后的航线
private newroute: any;
// 移动中的航线
private route: any;
// 方向点
private arrow: any = {
"type": "FeatureCollection",
"features": [[]]
};
// 起点
private origin = [];
// 终点
private destination = [];
// 记录动画帧数
private counter = 0;
// 两个点之间需要移动的步数
private nstep = 0;
// 航线移动需要的总步数
private steps = 0;
// 沿着航线添加一个移动的点, 这个点从起始点运动到终点。
private point: any;
// 地图对象
private map: any;
// LAYER ID
private trackPointLayerId = 'track-point-layer';
private baseLineLayerId = 'base-line-layer';
private trackLineLayerId1 = 'track-line-layer1';
private trackLineLayerId2 = 'track-line-layer2';
private trackLineLayerId3 = 'track-line-layer3';
private directionLayerId = 'direction-layer';
private markerLayerId = 'track-marker-layer';
// SOURCE ID
private trackPointSourceId = 'track-point-source';
private baseLineSourceId = 'base-line-source';
private trackLineSourceId = 'track-line-source';
private directionSourceId = 'direction-source';
private markerSourceId = 'track-marker-source'
//IMAGE ID
private trackPointImageId1 = 'airport-15'; // 默认移动物体
private trackPointImageId2 = 'move-custom'; //自定义移动问题Id
private directionImageId = 'direction-custom'; // 方向图片id
private markerImageId = 'marker-start'; // 起点marker图片Id
private markerImageId1 = 'marker-end'; // 终点marker图片Id
// 空数据
private emptyFeatures = {
"type": "FeatureCollection",
"features": []
};
// 可选参数
private option?: {
isBreakUp?: boolean, // 线是否打散 默认打散
step?: number, // 打散数即影响移动速度,打散程度越高移动越慢, isBreakUp为false时无效
shineLine?: boolean, // 是否发光线,默认不发光
isShowBaseLine: boolean // 是否先展示完整的轨迹线
baseLinePaint?: any, // 基础线图层样式,isShowBaseLine为true时才有效
linePaint?: any, // 覆盖-线图层样式
pointImageId?: string, // 移动物体图片ID
pointImagePath?: string, // 移动物体图片地址 当id与地址都存在时id优先
pointSize?: number, // 移动物体大小
directionImageId?: string, // 方向图片Id
directionImagePath?: string, // 方向图片地址 当id与地址都存在时id优先
directionNstep?: number, // 间隔几步一个方向
directionSize?: number, // 方向大小
markerImageId?: string, // marker图片Id
markerImagePath?: string, // marker图片地址 当id与地址都存在时id优先
markerSize?: number, // marker大小
viewFollow?: { // 开启视角跟随
pitch: number, //倾斜度
zoom: number, //缩放级别
}
};
/**
* 轨迹服务初始化
* @param map 地图对象
* @param line 线坐标数组
* @param option 可选参数集
*/
init(map: any, line: any, option?: {
isBreakUp?: boolean, // 线是否打散 默认打散
step?: number, // 打散数即影响移动速度,打散程度越高移动越慢, isBreakUp为false时无效
shineLine?: boolean, // 是否发光线,默认不发光
isShowBaseLine: boolean // 是否先展示完整的轨迹线
baseLinePaint?: any, // 基础线图层样式,isShowBaseLine为true时才有效
linePaint?: any, // 覆盖-线图层样式
pointImageId?: string, // 移动物体图片ID
pointImagePath?: string, // 移动物体图片地址 当id与地址都存在时id优先
pointSize?: number, // 移动物体大小
directionImageId?: string, // 方向图片Id
directionImagePath?: string, // 方向图片地址 当id与地址都存在时id优先
directionNstep?: number, // 间隔几步一个方向
directionSize?: number, // 方向大小
markerImageId?: string, // marker图片Id
markerImagePath?: string, // marker图片地址 当id与地址都存在时id优先
markerSize?: number, // marker大小
viewFollow?: { // 开启视角跟随
pitch: number, //倾斜度
zoom: number, //缩放级别
}
}) {
this.map = map;
this.line = line;
if (option) {
this.option = option;
}
// 添加航线数据
this.origin = line[0];
this.destination = line[line.length - 1];
// 是否打散
if (!this.option || (this.option && this.option.isBreakUp !== false)) {
this.nstep = this.option && this.option.step ? this.option.step : 200;
if (this.nstep > line.length) {
this.newroute = this.getRoute({
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': line
}
}, this.nstep, { units: 'kilometers' })
} else {
this.newroute = lineHelper(line);
}
} else {
this.newroute = lineHelper(line);
}
this.steps = this.newroute.geometry.coordinates.length - 1
this.route = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': []
}
}
]
};
this.point = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': []
}
}
]
};
this.clear();
this.addTrackBackLayer();
this.changeAnimateStatus('init');
}
/**
* 添加轨迹回放图层
*/
private addTrackBackLayer() {
if (!this.map) {
return;
}
/**
* 添加数据源
*/
if (!this.map.pmap.getSource(this.trackLineSourceId)) {
this.map.pmap.addSource(this.trackLineSourceId, {
'type': 'geojson',
'data': this.route
});
} else {
this.map.pmap.getSource(this.trackLineSourceId).setData({
'type': 'geojson',
'data': this.route
})
}
if (!this.map.pmap.getSource(this.trackPointSourceId)) {
this.map.pmap.addSource(this.trackPointSourceId, {
'type': 'geojson',
'data': this.point
});
} else {
this.map.pmap.getSource(this.trackPointSourceId).setData({
'type': 'geojson',
'data': this.point
})
}
/**
* 添加基础线图层
*/
if (this.option && this.option.isShowBaseLine) {
this.addBaseLine();
this.map.pmap.addLayer({
'id': this.baseLineLayerId,
'source': this.baseLineSourceId,
'type': 'line',
'paint': this.option && this.option.baseLinePaint ? this.option.baseLinePaint : {
'line-width': 8,
'line-blur': 3,
'line-opacity': 1,
'line-color': '#003DF5'
}
});
}
/**
* 添加轨迹发光效果线图层
*/
if (this.option && this.option.shineLine) {
// 在 addLayer 这里,选择合适的线样式,图标样式, 把航线及飞行动画效果最终呈现在地图上。
// 我设置了3条重叠的但样式不一样的 Line 来创造发光的航线!
this.map.pmap.addLayer({
'id': this.trackLineLayerId1,
'source': this.trackLineSourceId,
'type': 'line',
'paint': this.option && this.option.linePaint ? this.option.linePaint : {
'line-width': 8,
'line-blur': 3,
'line-opacity': 0.2,
'line