Cesium 航线飞行(第三人称跟随)

效果:

 1. 规划航线:

let positionArr = [
    {x: -2497416.6511379397, y: -4398264.4706970295, z: 3876875.3974358095},
    {x: -2490587.749623715, y: -4402803.334849232, z: 3876348.784933778},
    {x: -2484600.807545809, y: -4397341.415887679, z: 3886715.3400331396},
    {x: -2486705.891473638, y: -4392077.3543862775, z: 3891215.8287224886},
    {x: -2493470.9368140115, y: -4390936.265044111, z: 3887973.753169003},
    {x: -2498100.4272179785, y: -4394412.2608769955, z: 3880791.628977629},
    {x: -2497416.6511379397, y: -4398264.4706970295, z: 3876875.3974358095},
]; 

随意选取的几个点位,画线效果:

 2. 设置时间:

Cesium中的运动都是依靠时钟来进行。

//设置模拟时间
const setTime = () => {
    start = Cesium.JulianDate.fromDate(new Date(2023, 11, 17, 16)); //开始时间,可以随意设置
    //结束时间,因为设置了 6 个点位,到达每个点位的时间为10s,所以这里结束时间设为 60s 后
    let stop = Cesium.JulianDate.addSeconds(start, 60, 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; // 时间倍数
}

//每个位置对应相应的时间点
let positionProperty = null;
const computeCirclularFlight = () => {
    const property = new Cesium.SampledPositionProperty();
    for (let i = 0; i < positionArr.length; i++) {
        // 每隔10s进行采样,记录点的位置
        let time = Cesium.JulianDate.addSeconds(start, i * 10, new Cesium.JulianDate());
        property.addSample(time, positionArr[i]);
    }
    positionProperty = property;
}

 3. 加载glb模型:

//加载模型
const addModal = () => {
    modelEntity = viewer.entities.add({
        name: "飞机模型",
        position: positionProperty,
        // 根据位置移动自动计算方向
        orientation: new Cesium.VelocityOrientationProperty(positionProperty), 
        model: {
            uri: 'modals/fly.glb',
            scale: 5,
            minimumPixelSize: 128, // 最小的模型像素
            maximumScale: 20000, // 最大的模型像素
            clampAnimations: false, // 是否保持最后一针的动画
            show: true,
        },
    });
}

此时效果:

4. 第三人称视角跟随:

// 监听场景渲染
viewer.scene.preUpdate.addEventListener(setView);

// 第三人称视角跟随
const setView = () => {
    let center = modelEntity.position.getValue(viewer.clock.currentTime);
    let orientation = modelEntity.orientation.getValue(viewer.clock.currentTime);
    let transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
    transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center);
    viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-100, 0, 50))
}

5. 完整代码: 

<template>
    <div id="cesiumViewer"></div>
</template>

<script setup>
import * as Cesium from 'cesium';
import { onBeforeUnmount, onMounted } from 'vue';
let viewer, handler, start, positionProperty, modelEntity = null;

let positionArr = [
    {x: -2497416.6511379397, y: -4398264.4706970295, z: 3876875.3974358095},
    {x: -2490587.749623715, y: -4402803.334849232, z: 3876348.784933778},
    {x: -2484600.807545809, y: -4397341.415887679, z: 3886715.3400331396},
    {x: -2486705.891473638, y: -4392077.3543862775, z: 3891215.8287224886},
    {x: -2493470.9368140115, y: -4390936.265044111, z: 3887973.753169003},
    {x: -2498100.4272179785, y: -4394412.2608769955, z: 3880791.628977629},
    {x: -2497416.6511379397, y: -4398264.4706970295, z: 3876875.3974358095},
]; 

onMounted(() => {
    initCesium(); //初始化
    setTime();  //设置模拟时间
    computeCirclularFlight(); //航线范围
    addModal(); // 加载模型
    // drawLine(); //画线
})

//初始化
const initCesium = () => {
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzE5Mzk4YS01MzlkLTQzZTItOTMwOS02YTJjNmMxMzA2YmYiLCJpZCI6OTUyODEsImlhdCI6MTY4NTU3OTkxMn0.fBulnkkGPuGQEo6LrRIu-EO0S5DnPwwx5sLFnPPISDI';
    viewer = new Cesium.Viewer('cesiumViewer',{
        infoBox: false, // 禁用沙箱,解决控制台报错
        animation: false, // 是否创建动画小器件,左下角仪表
        baseLayerPicker: false, // 是否显示图层选择器
        fullscreenButton: false, // 是否显示全屏按钮
        geocoder: false, // 是否显示geocoder小器件,右上角查询按钮
        homeButton: false, // 是否显示Home按钮
        infoBox: false, // 是否显示信息框
        sceneModePicker: false, // 是否显示3D/2D选择器
        selectionIndicator: false, // 是否显示选取指示器组件
        timeline: false, // 是否显示时间轴
        navigationHelpButton: false, // 是否显示右上角的帮助按钮
        navigationInstructionsInitiallyVisible: false,  //是否显示帮助信息控件
        showRenderLoopErrors: false, // 是否显示渲染错误
        // 设置背景透明
        orderIndependentTranslucency: false,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
        shouldAnimate: true, //执行模型动画
        terrainProvider: Cesium.createWorldTerrain(), //地形 
    });

    viewer._cesiumWidget._creditContainer.style.display = 'none' // 隐藏logo
    viewer.scene.globe.enableLighting = true;   //启用使用场景光源照亮地球
    viewer.scene.globe.depthTestAgainstTerrain = true;  //启用深度测试
}

// 画线
const drawLine = () => {
    viewer.entities.add({
        name: "line",
        show: true,
        polyline: {
            positions: positionArr,
            width: 3,
            material: new Cesium.Color.fromCssColorString('#006EFF').withAlpha(.8),
        }
    })
}

//设置模拟时间
const setTime = () => {
    start = Cesium.JulianDate.fromDate(new Date(2023, 11, 17, 16)); //开始时间,可以随意设置
    //结束时间,因为设置了 6 个点位,到达每个点位的时间为10s,所以这里结束时间设为 60s 后
    let stop = Cesium.JulianDate.addSeconds(start, 60, 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 computeCirclularFlight = () => {
    const property = new Cesium.SampledPositionProperty();
    for (let i = 0; i < positionArr.length; i++) {
        // 每隔10s进行采样,记录点的位置
        let time = Cesium.JulianDate.addSeconds(start, i * 10, new Cesium.JulianDate());
        property.addSample(time, positionArr[i]);
    }
    positionProperty = property;
}

//加载模型
const addModal = () => {
    modelEntity = viewer.entities.add({
        name: "飞机模型",
        position: positionProperty,
        orientation: new Cesium.VelocityOrientationProperty(positionProperty),  // 根据位置移动自动计算方向
        model: {
            uri: 'modals/fly.glb',
            scale: 5,
            minimumPixelSize: 128, // 最小的模型像素
            maximumScale: 20000, // 最大的模型像素
            clampAnimations: false, // 是否保持最后一针的动画
            show: true,
        },
    });

    // 监听场景渲染
    viewer.scene.preUpdate.addEventListener(setView);
}

// 第三人称视角跟随
const setView = () => {
    let center = modelEntity.position.getValue(viewer.clock.currentTime);
    let orientation = modelEntity.orientation.getValue(viewer.clock.currentTime);
    let transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
    transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center);
    viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-100, 0, 50))
}

onBeforeUnmount(() => {
    viewer.scene.preUpdate.removeEventListener(setView);
})
</script>

<style lang="less" scoped>
</style>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值