mapbox+turf实现轨迹回放组件

     **最近项目有个需求需要实现轨迹回放组件的封装,要求轨迹线颜色可配置,轨迹回放速度可调,移动物体可配置,能够获取轨迹进度,拖动轨迹进度实现轨迹移动等等需求**

轨迹组件类

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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值