cesium实现轨迹播放CZML

1.创建CZML数据结构

 const czml=[{
                id: "document",
                name: "CZML",
                version: "1.0",
                clock: {
                    interval: "2022-08-04T10:00:00Z/2022-08-04T15:00:00Z", // 时间段
                    currentTime: "2022-08-04T10:00:00Z", // 开始时间
                    multiplier: 1, // 已多少倍速播放
                    range: "CLAMPED",
                },
            },
            {
                id: "path",
                name: "path with GPS flight data",
                description: "",
                availability: "2022-08-04T10:00:00Z/2022-08-04T15:00:00Z", // 时间段 
                path: {
                    material: {
                        //轨迹颜色
                        polylineOutline: {
                            color: {
                                rgba: color,
                            },
                            outlineColor: {
                                rgba: outlineColor,
                            },
                            outlineWidth: outlineWidth,
                        },
                    },
                    width: width,
                    leadTime: 0, // 提前绘制时间
                },
                model: {
                    gltf: "模型地址",
                    scale: 0.1,
                    minimumPixelSize: 100,
                },
                position: {
                    epoch: "2022-08-04T10:00:00Z", // 该项开始绘制路径时间
                    cartographicDegrees: [
                       0,113,20,1000,//时间为秒,经度,维度,高度(米)
                    ],//数据
                },
            },
        ]

2.添加控制并监听

// 更新播放时间
            const updateCurrentTime = (index) => {
                    let time = new Date(Number(data[index].tms));
                    viewer.clockViewModel.currentTime = Cesium.JulianDate.fromDate(time);
                }
                // 变更播放状态
            const updatePlayStatus = (state) => {
                    viewer.clock.canAnimate = state;
                    viewer.clock.shouldAnimate = state;
                }
                //变更倍数
            const updateCurrentMultiplier = (multiplier) => {
                viewer.clockViewModel.multiplier = multiplier;
            }


// 监听播放状态
            Cesium.knockout.getObservable(viewer.clockViewModel, 'shouldAnimate').subscribe(function(isAnimating) {
                if (isAnimating) {
                    console.log('Cesium clock is animating.');
                } else {
                    console.log('Cesium clock is paused.');
                }
            });

            // 检测实时播放的时间轴
            Cesium.knockout.getObservable(viewer.clockViewModel, 'currentTime').subscribe(function(clockTime) {
              
               

                //设置航向角,根据返回数据设置
                let cartesian3 = Cesium.Cartesian3.fromDegrees(
                    Number(returnData.list[playIndex].lng),
                    Number(returnData.list[playIndex].lat),
                    Number(returnData.list[playIndex].height) / 100 // 高度
                );
                let heading = Cesium.Math.toRadians((returnData.list[playIndex].yaw) - 90);
                let pitch = Cesium.Math.toRadians(returnData.list[playIndex].pitch);
                let roll = Cesium.Math.toRadians(returnData.list[playIndex].roll);
                let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
                entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
                    cartesian3,
                    hpr
                );
                // entity.orientation
            });

            // 设置播放状态
            // viewer.clockViewModel.shouldAnimate = true;
            viewer.dataSources
                .add(Cesium.CzmlDataSource.load(czml))
                .then(function(ds) {

                    let s = ds.entities.getById("path");

                    viewer.trackedEntity = s; // 设置相机跟随

                    entity = s; //记录实例,方便改变方向角
                    // 设置图标执行下个点
                    //   s.orientation = new Cesium.VelocityOrientationProperty(s.position);
                    //   s.billboard.alignedAxis = new Cesium.VelocityVectorProperty(
                    //     s.position,
                    //     true
                    //   );

                });
        

3.在js中使用

//获取数据
axios.get(url).then(res=>{
   czml[1].position.cartographicDegrees =res 
updatePlayStatus(true)//改变运动状态,启动动画
})

4.以下是我在项目中封装的完整代码,通过解析后台csv文件数据得到经纬度

import axios from "axios";
const d3 = require("d3-dsv");
export function setCzmlData(viewer, config = {}) {
    let {
        url, // csv文件
        playEvene, // 播放事件,返回播放状态
        endPlay, // 结束事件,返回最后一个点
        playChange, // 播放改变时间,返回当前播放点,播放点对应的数据,时间
        color = [170, 255, 85, 255], // 线条颜色
        width = 6, // 线条大小
        outlineColor = [170, 255, 85, 255], // 边框颜色
        outlineWidth = 6, // 边框大小
        modelUrl = "模型地址", // 模型地址
    } = config;
    return new Promise((resolve, reject) => {
        if (!url) {
            return reject("csv文件不能为空")
        }
        const czml = [{
                id: "document",
                name: "CZML",
                version: "1.0",
                clock: {
                    interval: "2022-08-04T10:00:00Z/2022-08-04T15:00:00Z", // 时间段
                    currentTime: "2022-08-04T10:00:00Z", // 开始时间
                    multiplier: 1, // 已多少倍速播放
                    range: "CLAMPED",
                },
            },
            {
                id: "path",
                name: "path with GPS flight data",
                description: "",
                availability: "2022-08-04T10:00:00Z/2022-08-04T15:00:00Z", // 时间段 
                path: {
                    material: {
                        polylineOutline: {
                            color: {
                                rgba: color,
                            },
                            outlineColor: {
                                rgba: outlineColor,
                            },
                            outlineWidth: outlineWidth,
                        },
                    },
                    width: width,
                    leadTime: 0, // 提前绘制时间
                },
                model: {
                    gltf: modelUrl,
                    scale: 0.1,
                    minimumPixelSize: 100,
                },
                position: {
                    epoch: "2022-08-04T10:00:00Z", // 该项开始绘制路径时间
                    cartographicDegrees: [],
                },
            },
        ];
        let entity = ''
        axios.get(url).then((res) => {
            let index = res.data.indexOf("End") + 4;
            let list = res.data.substr(index);
            let data = d3.csvParse(list);
            let returnData = generateData(data)
            let newData = [];
            let time = Number(data[0].tms);

            let start = new Date(Number(data[0].tms)).toJSON().trim()
            let end = new Date(Number(data[data.length - 1].tms)).toJSON().trim()

            czml[0].clock.currentTime = start;
            czml[0].clock.interval = `${start}/${end}`;
            czml[1].availability = `${start}/${end}`;
            czml[1].position.epoch = `${start}`;

            for (let i = 0; i < data.length; i++) {
                let item = data[i];
                let item1 = returnData.list[i]
                let tms = Number(item.tms) - time;
                newData.push(
                    tms / 1000, // 时间,秒
                    Number(item1.lng),
                    Number(item1.lat),
                    Number(item.height) / 100 // 高度
                );
            }

            czml[1].position.cartographicDegrees = newData;

            // 更新播放时间
            const updateCurrentTime = (index) => {
                    let time = new Date(Number(data[index].tms));
                    viewer.clockViewModel.currentTime = Cesium.JulianDate.fromDate(time);
                }
                // 变更播放状态
            const updatePlayStatus = (state) => {
                    viewer.clock.canAnimate = state;
                    viewer.clock.shouldAnimate = state;
                }
                //变更倍数
            const updateCurrentMultiplier = (multiplier) => {
                viewer.clockViewModel.multiplier = multiplier;
            }

            let params = {
                returnData,
                czml,
                updateCurrentTime,
                updatePlayStatus,
                updateCurrentMultiplier
            }

            resolve(params);

            // 监听播放状态
            Cesium.knockout.getObservable(viewer.clockViewModel, 'shouldAnimate').subscribe(function(isAnimating) {
                if (isAnimating) {
                    console.log('Cesium clock is animating.');
                } else {
                    console.log('Cesium clock is paused.');
                }
                playEvene && playEvene(isAnimating)
            });
            // 检测实时播放的时间轴
            let playIndex = 1;
            Cesium.knockout.getObservable(viewer.clockViewModel, 'currentTime').subscribe(function(clockTime) {
                // 播放状态
                let shouldAnimate = viewer.clockViewModel.shouldAnimate;
                // 当前时间轴播放时间
                let currentTime = clockTime.toString();
                let tms = new Date(currentTime).getTime();

                // 播放结束
                if (parseInt(tms / 100) >= parseInt(Number(data[data.length - 1].tms) / 100)) {
                    endPlay && endPlay(data[data.length - 1], data.length - 1);
                    return false;
                }
                if (shouldAnimate) {
                    if (tms >= Number(data[playIndex].tms)) {
                        playIndex++;
                    }
                } else {
                    for (let i = 0; i < data.length; i++) {
                        if (Number(data[i].tms) >= tms) {
                            playIndex = i + 1;
                            break;
                        }
                    }
                }
                // 播放监听事件
                playChange && playChange(playIndex, returnData.list[playIndex], currentTime)

                //设置航向角,根据返回数据设置
                let cartesian3 = Cesium.Cartesian3.fromDegrees(
                    Number(returnData.list[playIndex].lng),
                    Number(returnData.list[playIndex].lat),
                    Number(returnData.list[playIndex].height) / 100 // 高度
                );
                let heading = Cesium.Math.toRadians((returnData.list[playIndex].yaw) - 90);
                let pitch = Cesium.Math.toRadians(returnData.list[playIndex].pitch);
                let roll = Cesium.Math.toRadians(returnData.list[playIndex].roll);
                let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
                entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
                    cartesian3,
                    hpr
                );
                // entity.orientation
            });

            // 设置播放状态
            // viewer.clockViewModel.shouldAnimate = true;
            viewer.dataSources
                .add(Cesium.CzmlDataSource.load(czml))
                .then(function(ds) {

                    let s = ds.entities.getById("path");

                    viewer.trackedEntity = s; // 设置相机跟随

                    entity = s; //记录实例,方便改变方向角
                    // 设置图标执行下个点
                    //   s.orientation = new Cesium.VelocityOrientationProperty(s.position);
                    //   s.billboard.alignedAxis = new Cesium.VelocityVectorProperty(
                    //     s.position,
                    //     true
                    //   );

                });
        });
    })
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值