Cesium 實(shí)現(xiàn)一個(gè) 飛機(jī)漫游 飛行效果

哈嘍,大家好 我是xy???????。最近剛剛?cè)肟?Cesium , 隨手寫了幾個(gè)練習(xí)的小案例,這篇文章給大家分享一個(gè) Cesium 實(shí)現(xiàn)的飛機(jī)漫游飛行的效果

前置準(zhǔn)備
案例中采用 Vue3 來(lái)搭建,還不會(huì)搭建 Vue3 腳手架的同學(xué)可以看下我之前的文章:

Vite2 + Vue3 + TypeScript + Pinia 搭建一套企業(yè)級(jí)的開(kāi)發(fā)腳手架【值得收藏】

本文的主題是講解 實(shí)現(xiàn)一個(gè)飛機(jī)飛行效果 , 搭建過(guò)程這里不做過(guò)多的介紹.

安裝 Cesium
安裝方式有兩種:

第一種是使用 npm 方式來(lái)安裝
npm i cesium --save
在項(xiàng)目根目錄新增配置文件 vue.config.js ,如下

const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')
const path = require('path')

const debug = process.env.NODE_ENV !== 'production'
let cesiumSource = './node_modules/cesium/Source'
let cesiumWorkers = '../Build/Cesium/Workers'
module.exports = {
    baseUrl: '',
    devServer: {
        port: 8090 //修改服務(wù)端口號(hào)
    },
    outputDir: 'docs', //設(shè)置 build 輸出目錄
    configureWebpack: {
        output: {
            sourcePrefix: ' '
        },
        amd: {
            toUrlUndefined: true
        },
        resolve: {
            alias: {
                'vue$': 'vue/dist/vue.esm.js',
                '@': path.resolve('src'),
                'cesium': path.resolve(__dirname, cesiumSource)
            }
        },
        plugins: [
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'ThirdParty/Workers'), to: 'ThirdParty/Workers'}]),
            new webpack.DefinePlugin({
                CESIUM_BASE_URL: JSON.stringify('./')
            })
        ],
        module: {
            unknownContextCritical: /^.\/.*$/,
            unknownContextCritical: false

        }
    }
}

main.js 中新增引用

import Cesium from 'cesium/Cesium' //from 中 cesium 指向的是vue.config.js中 alias對(duì)象中的別名
// noinspection ES6UnusedImports
import widget from 'cesium/Widgets/widgets.css'

第二種直接下載官方的包引入
下載地址:https://cesium.com/platform/cesiumjs/

本文講解的案例使用的第二種方式,直接下載后放到項(xiàng)目的 public 文件夾下

在這里插入圖片描述











在 index.html 中直接引入即可

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <!-- 引入 cesium -->
    <script src="./cesium/Build/Cesium/Cesium.js"></script>
    <link rel="stylesheet" href="./cesium/Build/Cesium/Widgets/widgets.css">

  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Cesium 初始化
新建一個(gè) vue 組件,用于初始化 Cesium

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

<script setup>
import { onMounted } from "vue";

const token ="token自己注冊(cè)賬號(hào)申請(qǐng)即可";

onMounted(() => {
  Cesium.Ion.defaultAccessToken = token;

  var viewer = new Cesium.Viewer("cesiumContainer", {
    animation: true, //是否創(chuàng)建動(dòng)畫小器件,左下角儀表
    shouldAnimate: true,
    baseLayerPicker: true, //是否顯示圖層選擇器
    fullscreenButton: true, //是否顯示全屏按鈕
    geocoder: true, //是否顯示geocoder小器件,右上角查詢按鈕
    homeButton: true, //是否顯示Home按鈕
    infoBox: true, //是否顯示信息框
    sceneModePicker: true, //是否顯示3D/2D選擇器
    selectionIndicator: true, //是否顯示選取指示器組件
    timeline: true, //是否顯示時(shí)間軸
    navigationHelpButton: true, //是否顯示右上角的幫助按鈕
    scene3DOnly: true, //如果設(shè)置為true,則所有幾何圖形以3D模式繪制以節(jié)約GPU資源
    clock: new Cesium.Clock(), //用于控制當(dāng)前時(shí)間的時(shí)鐘對(duì)象
    selectedImageryProviderViewModel: undefined, //當(dāng)前圖像圖層的顯示模型,僅baseLayerPicker設(shè)為true有意義
    imageryProviderViewModels: Cesium.createDefaultImageryProviderViewModels(), //可供BaseLayerPicker選擇的圖像圖層ProviderViewModel數(shù)組
    selectedTerrainProviderViewModel: undefined, //當(dāng)前地形圖層的顯示模型,僅baseLayerPicker設(shè)為true有意義
    terrainProviderViewModels: Cesium.createDefaultTerrainProviderViewModels(), //可供BaseLayerPicker選擇的地形圖層ProviderViewModel數(shù)組
    terrainProvider: new Cesium.EllipsoidTerrainProvider(), //地形圖層提供者,僅baseLayerPicker設(shè)為false有意義
    fullscreenElement: document.body, //全屏?xí)r渲染的HTML元素,
    useDefaultRenderLoop: true, //如果需要控制渲染循環(huán),則設(shè)為true
    targetFrameRate: undefined, //使用默認(rèn)render loop時(shí)的幀率
    showRenderLoopErrors: false, //如果設(shè)為true,將在一個(gè)HTML面板中顯示錯(cuò)誤信息
    automaticallyTrackDataSourceClocks: true, //自動(dòng)追蹤最近添加的數(shù)據(jù)源的時(shí)鐘設(shè)置
    contextOptions: undefined, //傳遞給Scene對(duì)象的上下文參數(shù)(scene.options)
    sceneMode: Cesium.SceneMode.SCENE3D, //初始場(chǎng)景模式
    mapProjection: new Cesium.WebMercatorProjection(), //地圖投影體系
    dataSources: new Cesium.DataSourceCollection(),
    //需要進(jìn)行可視化的數(shù)據(jù)源的集合
  });
});
</script>

效果如下:
在這里插入圖片描述

加載 CZML 數(shù)據(jù)
什么是 CZML 數(shù)據(jù)呢
CZML 是 cesium 中很重要的一個(gè)概念,也是一個(gè)亮點(diǎn),CZML 使得 cesium 很酷很炫地展示動(dòng)態(tài)數(shù)據(jù)成為可能。
CZML 是一種 JSON 格式的字符串,用于描述與時(shí)間有關(guān)的動(dòng)畫場(chǎng)景,CZML 包含點(diǎn)、線、地標(biāo)、模型、和其他的一些圖形元素,并指明了這些元素如何隨時(shí)間而變化。某種程度上說(shuō), Cesium 和 CZML 的關(guān)系就像 Google Earth 和 KML。
CZML 的一個(gè)典型結(jié)構(gòu)如下。片段描述了兩個(gè)包(packet,這里每個(gè)包描述了一個(gè)點(diǎn)),每個(gè)包的 id,position 和 color。
CZML 比較特殊的是跟時(shí)間序列相關(guān)的屬性
[
    {
      id: "document",
      version: "1.0",
      clock: {
        interval: "2018-07-19T15:18:00Z/2018-07-19T15:18:30Z", // 開(kāi)始時(shí)間-結(jié)束時(shí)間
        currentTime: "2018-07-19T15:18:00Z", // 當(dāng)前時(shí)間
        multiplier: 5, // 軌跡運(yùn)行的速度
        range: "LOOP_STOP",
        step: "SYSTEM_CLOCK_MULTIPLIER",
      },
    },
    {
      id: "CesiumMilkTruck",
      model: {
        gltf: "/Cesium_Air.glb",
      },
      // 位置信息
      position: {
        interpolationAlgorithm: "LINEAR", //插值算法
        forwardExtrapolationType: "HOLD", //插值算法
        cartesian: [
          "2018-07-19T15:18:00Z",
          1216348.1632364073,
          -4736348.958775471,
          4081284.5528982095,
          "2018-07-19T15:18:30Z",
          1216369.1229444197,
          -4736377.467107148,
          4081240.888485707,
        ],
      },
      // 模型方向信息
      orientation: {
        velocityReference: "#position",
        // unitQuaternion: [
        //   0.3084011337938999, 0.3210181022701266, -0.45850421987074924,
        //   0.7686388857813198,
        // ],
      },
    },
    {
      id: "Polyline",
      polyline: {
        positions: {
          cartesian: [
            1216348.1632364073, -4736348.958775471, 4081284.5528982095,
            1216369.1229444197, -4736377.467107148, 4081240.888485707,
          ],
        },
        material: {
          polylineOutline: {
            color: {
              rgba: [255, 255, 0, 255],
            },
            outlineColor: {
              rgba: [0, 0, 0, 255],
            },
            outlineWidth: 2,
          },
        },
        width: 10,
        clampToGround: true, // 線條緊貼地面
      },
    },
  ];
如何加載
貼心的 Cesium 已經(jīng)給我們提供好了加載的方法,不需要我們做任何特殊的處理

// 加載 CZML
const dataSourcePromise = viewer.dataSources.add(
    Cesium.CzmlDataSource.load(czml)
  );
// 加載完成后移動(dòng)相機(jī)跟蹤目標(biāo)
  dataSourcePromise.then(function (dataSource) {
    viewer.trackedEntity = dataSource.entities.getById("CesiumMilkTruck");
  });

如果你想要的獲取到完整的代碼,可以加我文末微信,歡迎小伙伴們來(lái)找我一起學(xué)習(xí)交流

另外,以后應(yīng)該會(huì)經(jīng)常出一些Cesium案例之類的,歡迎大家關(guān)注我的視頻號(hào),一起學(xué)習(xí)交流


作者:前端小菜雞之菜雞互啄


歡迎關(guān)注微信公眾號(hào) :前端開(kāi)發(fā)愛(ài)好者