vue+cesium: 渔船轨迹绘制(可运动)(TrailLineAnimate.js)

355 阅读1分钟

渔船轨迹 TrailLineAnimate.js

/*
* 说明:   渔船轨迹
*/


import * as Cesium from "cesium/Cesium.js";
import config from "./config";


export default class TrailLineAnimate {
    constructor(viewer) {
        this.viewer = viewer;
        this.initEvents();
    }

    //初始化事件
    initEvents() {
        //动画开始事件
        this.AnimateStartEvent = new Cesium.Event();
        //站点到达事件
        this.StopsArrivedEvent = new Cesium.Event(); //传入站点信息
        //动画结束事件
        this.AnimateEndEvent = new Cesium.Event();
    }

    //开始播放轨迹
    play(stops, speed) {
        //执行前先停止
        this.stop()
        setTimeout(() => {
            this.stops = stops;
            // this.params = stops
            this.speed = speed;
            this.addTrailLine(this.getPositions());
            this.addTickEvent();
            this.isAnimating = true;
            this.nextStopsIndex = 0;
        }, 3000)

    }

    //获取点串
    getPositions() {
        let positions = [];
        this.stops.forEach(stop => {
            let lon = parseFloat(stop.e / 10000000)
            let lat = parseFloat(stop.f / 10000000)
            positions.push(Cesium.Cartesian3.fromDegrees(lon, lat, 0))
        });
        console.log('positions', positions)
        return positions;
    }

    //添加轨迹线
    addTrailLine(positions) {
        this.trailLineInfo = this.getTrailLineInfo(positions, this.speed || 25);
        let startTime = Cesium.JulianDate.fromDate(new Date()); //Cesium.JulianDate.fromDate(new Date());
        let stopTime = Cesium.JulianDate.addSeconds(startTime, this.trailLineInfo.timeInfo.timeSum, new Cesium.JulianDate());
        this.viewer.clock.startTime = startTime.clone();
        this.viewer.clock.stopTime = stopTime.clone();
        this.viewer.clock.currentTime = startTime.clone();
        this.viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;

        let property = this.computeCirclularFlight(positions, startTime, this.trailLineInfo.timeInfo.siteTimes);
        this.addAminateModel(startTime, stopTime, property);
        this.addAnimateLine();
        this.calStopsTimes(startTime, this.trailLineInfo.timeInfo.siteTimes);
    }

    //获取飞行的动画点位
    computeCirclularFlight(pArr, startTime, siteTimes) {
        var property = new Cesium.SampledPositionProperty();
        for (var i = 0; i < pArr.length; i++) {
            const time = Cesium.JulianDate.addSeconds(startTime, siteTimes[i], new Cesium.JulianDate());
            property.addSample(time, pArr[i]);
        }
        return property;
    }

    //计算每个站点的时间
    calStopsTimes(startTime, siteTimes) {
        this.stopsTimes = [];
        siteTimes.forEach(item => {
            const date = Cesium.JulianDate.addSeconds(startTime, item, new Cesium.JulianDate());
            this.stopsTimes.push(date);
        });
    }

    //添加动画模型
    addAminateModel(startTime, stopTime, property) {
        this.animateModel = this.viewer.entities.add({
            availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                start: startTime,
                stop: stopTime
            })]),
            position: property,
            orientation: new Cesium.VelocityOrientationProperty(property),
            model: {
                uri: config.mapUrl.gltf.shipBoat,
                scale: 1
            }
        });
        console.log('addAminateModel', this.animateModel)
    }

    //添加动画线
    addAnimateLine() {
        this.linePositions = [];
        this.animateLine = this.viewer.entities.add({
            polyline: {
                positions: new Cesium.CallbackProperty(e => {
                    this.linePositions.push(this.animateModel.position.getValue(
                            this.viewer.clock.currentTime
                    ));
                    return this.linePositions;
                }, false),
                width: 5,
                material: Cesium.Color.LAWNGREEN,
                clampToGround: true
            },
        })
    }

    //停止
    stop() {
        this.clear();
        this.removeTickEvent();
        this.isAnimating = false;
    }

    //添加时间监听事件
    addTickEvent() {
        this.viewer.clock.onTick.addEventListener(this.tickEventHandler, this);
    }

    //移除时间监听事件
    removeTickEvent() {
        this.viewer.clock.onTick.removeEventListener(this.tickEventHandler, this);
    }

    //时间监听事件处理函数
    tickEventHandler() {
        const currentTime = this.viewer.clock.currentTime;
        const nextStopsTime = this.stopsTimes[this.nextStopsIndex];
        if (Cesium.JulianDate.equalsEpsilon(currentTime, nextStopsTime, 0.1)) {
            //触发站点到达事件
            this.StopsArrivedEvent.raiseEvent(this.stops[this.nextStopsIndex], this.nextStopsIndex);
            this.nextStopsIndex++; //通过时间判断当前到达的站点
            if (this.nextStopsIndex == this.stopsTimes.length) {
                //最后一个站点结束
                this.removeTickEvent();
                this.isAnimating = false;
                this.AnimateEndEvent.raiseEvent();
            }
        }
    }

    //清除轨迹
    clear() {
        this.viewer.entities.remove(this.animateModel);
        this.animateModel = undefined;

        this.viewer.entities.remove(this.animateLine);
        this.animateLine = undefined;
        console.log('this.animateModel', this.animateModel)
        console.log('this.animateLine', this.animateLine)
    }

    //计算笛卡尔坐标串的距离
    spaceDistance(positions) {
        let distance = 0;
        let c1, c2, geodesic, sD;
        for (let i = 0; i < positions.length - 1; i++) {
            if(!positions[i] || !positions[i + 1]) return
            c1 = Cesium.Cartographic.fromCartesian(positions[i]);
            c2 = Cesium.Cartographic.fromCartesian(positions[i + 1]);
            /**根据经纬度计算出距离**/
            geodesic = new Cesium.EllipsoidGeodesic();
            geodesic.setEndPoints(c1, c2);
            sD = geodesic.surfaceDistance;
            //返回两点之间的距离
            sD = Math.sqrt(Math.pow(sD, 2) + Math.pow(c2.height - c1.height, 2));
            distance = distance + sD;
        }
        return distance.toFixed(3);
    }

    // GPS点串转笛卡尔点串 coordinates=[[x,y,z],[x,y,z]]格式
    fromCoordinatesToCartesian3(coordinates) {
        let ps = [];
        coordinates.forEach(item => {
            ps.push(Cesium.Cartesian3.fromDegrees(item[0], item[1], item[2]));
        });
        return ps;
    }

    //获取轨迹信息 传入笛卡尔坐标点串和速度
    getTrailLineInfo(positions, speed) {
        let trailLineInfo = {};
        trailLineInfo.timeInfo = this.getSiteTimes(positions, speed);
        trailLineInfo.startTime = Cesium.JulianDate.fromDate(new Date()); //Cesium.JulianDate.fromDate(new Date());//开始时间
        trailLineInfo.stopTime = Cesium.JulianDate.addSeconds(trailLineInfo.startTime, trailLineInfo.timeInfo.timeSum, new Cesium.JulianDate()); //结束时间
        return trailLineInfo;
    }

    //获取每个站点的时间秒及总时间
    getSiteTimes(positions, speed) {
        let times = [0]; //第0个时间为0秒
        let timeSum = 0;
        for (var i = 1; i < positions.length; i++) {
            timeSum += this.spaceDistance([positions[i - 1], positions[i]]) / speed;
            times.push(timeSum);
        }
        console.log('getSiteTimes', {
            timeSum: timeSum,
            siteTimes: times
        })
        return {
            timeSum: timeSum,
            siteTimes: times
        }
    }
}