原生Cesium实现飞行浏览功能

功能介绍:在地图上手动绘制站点,并在站点间生成飞行路线,点击开始按钮沿飞行路线进行飞行,在每个站点停顿一段时间后继续向下一个站点飞行。可再飞行过程中跳转到任意站点继续完成飞行。

代码:

<div>

                    <el-checkbox v-model="isLineVisible" @change="toggleLineVisibility" class="flex-container-left"

                        label="是否显示路线" size="large" />

                    <el-checkbox @change="toggleStopVisibility" v-model="isStopVisible" label="是否显示站点" size="large" />

                </div>

                <div class="selectdrop">

                    <span

                        :style="{ color: 'white', position: 'absolute', top: '4.5rem', left: '1.0625rem', fontSize: '14px', fontFamily: 'Source' }">站点</span>

                    <el-select v-model="index" id="stopList" popper-class="custom-select" placeholder="请选择站点"

                        :teleported="false">

                        <el-option v-for="item in allIndex" :key="item.value" :label="item.label" :value="item.value"

                            @click="changesite">

                        </el-option>

                    </el-select>

                </div>

                <div @click="addPoint" class="content-button"

                    :style="{ height: '1.9375rem', left: ' 2.1375rem', bottom: '4.9375rem' }">

                    添加站点

                </div>

                <div @click="play" class="content-button"

                    :style="{ height: '1.9375rem', right: ' 2.1375rem', bottom: '4.9375rem' }">

                    开始

                </div>

                <div @click="pause" class="content-button"

                    :style="{ height: '1.9375rem', left: '2.1375rem', bottom: '1.9375rem', backgroundColor: '#6C8DAE', border: '1px solid #6C8DAE' }">

                    暂停

                </div>

                <div @click="stop" class="content-button"

                    :style="{ height: '1.9375rem', right: ' 2.1375rem', bottom: '1.9375rem', backgroundColor: '#B73A3A', border: '0', }">

                    结束

                </div>

<script setup>

const isStopVisible = ref(false);

const isLineVisible = ref(false);

const entities = [];

const lineEntities = [];

// 添加站点

const addPoint = () => {

    const handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas);

    handler.setInputAction((click) => {

        const cartesian = window.viewer.camera.pickEllipsoid(click.position, window.viewer.scene.globe.ellipsoid);

        if (cartesian) {

            const cartographic = Cesium.Cartographic.fromCartesian(cartesian);

            const lon = Cesium.Math.toDegrees(cartographic.longitude);

            const lat = Cesium.Math.toDegrees(cartographic.latitude);

            const newSite = { label: `站点${allIndex.length + 1}`, value: allIndex.length, position: { lon, lat } };

            allIndex.push(newSite);

            addEntities();

        }

        handler.destroy();

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

};

// 站点显隐控制

const toggleStopVisibility = () => {

    entities.forEach(entity => {

        entity.show = isStopVisible.value;

    });

};

// 路线显隐控制

const toggleLineVisibility = () => {

    lineEntities.forEach(entity => {

        entity.show = isLineVisible.value;

    });

};

const handleCloseModal = () => {

    visible.value = false;

    // 移除地图上的路线和站点

    entities.forEach(entity => {

        viewer.entities.remove(entity);

    });

    lineEntities.forEach(lineEntity => {

        viewer.entities.remove(lineEntity);

    });

    entities.length = 0;

    lineEntities.length = 0;

};

const addEntities = () => {

    // 清除现有站点和路线

    entities.forEach(entity => viewer.entities.remove(entity));

    lineEntities.forEach(lineEntity => viewer.entities.remove(lineEntity));

    entities.length = 0;

    lineEntities.length = 0;

    // 添加站点标记

    allIndex.forEach(site => {

        const entity = viewer.entities.add({

            position: Cesium.Cartesian3.fromDegrees(site.position.lon, site.position.lat, 100),

            point: {

                pixelSize: 10,

                color: Cesium.Color.RED,

                outlineColor: Cesium.Color.WHITE,

                outlineWidth: 2,

            },

        });

        entities.push(entity);

    });

    // 生成站点之间的路线

    for (let i = 0; i < allIndex.length - 1; i++) {

        const start = allIndex[i].position;

        const end = allIndex[i + 1].position;

        const lineEntity = viewer.entities.add({

            polyline: {

                positions: Cesium.Cartesian3.fromDegreesArrayHeights([

                    start.lon, start.lat, 100,

                    end.lon, end.lat, 100

                ]),

                width: 5,

                material: Cesium.Color.YELLOW,

            },

            show: isLineVisible.value

        });

        lineEntities.push(lineEntity);

    }

    // 初始化时根据 isStopVisible 的值设置站点的显示/隐藏

    toggleStopVisibility();

    // 初始化时根据 isLineVisible 的值设置路线的显示/隐藏

    toggleLineVisibility();

};

watch(() => visible.value, (newVal) => {

    if (newVal) {

        addEntities();

    }

    emits("update:visible", newVal);

});

watch(() => props.visible, (newVal) => {

    visible.value = props.visible;

    if (visible.value) {

        addEntities();

    }

});

watch(isStopVisible, (newVal) => {

    toggleStopVisibility();

});

watch(isLineVisible, (newVal) => {

    toggleLineVisibility();

});

const changesite = () => {

    // 获取当前选择的站点

    const selectedSite = allIndex[index.value];

    const nextSite = allIndex[index.value + 1] || allIndex[index.value]; // 获取下一个站点,如果没有下一个站点则朝向当前站点

    if (selectedSite) {

        stop(); // 停止当前飞行

        currentIndex = index.value; // 设置当前索引为新选择的站点

        // 计算heading朝向

        const heading = computeHeading(selectedSite.position, nextSite.position);

        // 跳转到选择的站点并设置视线朝向下一个站点

        viewer.camera.flyTo({

            destination: Cesium.Cartesian3.fromDegrees(selectedSite.position.lon, selectedSite.position.lat, 200),

            orientation: {

                heading: heading,

                pitch: Cesium.Math.toRadians(-30), // 设置视线的俯仰角

                roll: 0.0

            },

            duration: 1 // 设置一个较短的飞行时间

        });

    }

}

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Cesium是一个用于创建3D地球和地图的JavaScript库。要在Cesium实现飞机飞行,你可以首先创建一个代表飞机的3D模型,并将其添加到Cesium场景中。然后,你可以使用Cesium的实体(Entity)和样条路径(Spline)功能来模拟飞行路径。 首先,你需要在Cesium中加载飞机的3D模型。你可以使用Cesium的3D模型加载器来加载模型文件,例如Gltf或Collada格式的文件。加载模型后,你可以将其添加到Cesium的场景(Scene)中。 接下来,你可以使用实体(Entity)来表示飞机。实体是Cesium中的一个概念,它代表场景中的一个可视对象。你可以为飞机创建一个实体,并设置其位置、方向和姿态等属性。通过更新实体的属性,你可以模拟飞机在场景中的移动和旋转。 为了实现飞行路径,你可以使用样条路径(Spline)功能Cesium提供了一个样条路径插值器(CatmullRomSpline)来生成平滑的飞行路径。你可以根据你想要的路径点的位置和时间信息,使用插值器来计算出飞机在每个时间点的位置。然后,通过设置实体的位置属性,让飞机沿着计算出的路径进行飞行。 最后,你可以使用Cesium的时间控制功能来控制飞行的速度和时间进度。通过调整时间的流逝速度,你可以模拟飞机的飞行速度。你还可以使用Cesium的摄像机控制功能来跟踪飞机,使其在飞行过程中始终保持在视野中心。 总结来说,要在Cesium实现飞机飞行,你需要加载飞机模型、创建实体表示飞机、使用样条路径生成飞行路径,并使用时间和摄像机控制功能来控制飞行过程。这样,你就可以在Cesium实现一个基本的飞机飞行效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值