三維地球視覺化從入門到進階 - 基礎詳解

語言: CN / TW / HK

本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!

哈嘍,大家好 我是 xy👨🏻‍💻。這篇文章是 Cesium 三維地球視覺化從入門到進階專欄的第一篇,從今天起,讓我帶著各位一起探索 CesiumJS 的程式設計世界吧

前言

🎯 從今天起開始陸續的更新 Cesium 三維地球視覺化從入門到進階專欄的系列文章了, 如果你也對 三維視覺化比較感興趣的話,歡迎關注我一起學習

🎯 本次專欄所有案例都基於 Vue3 + Vite3 + TypeScript + CesiumJS 開發,並且所有案列的程式碼都會統一放到 github倉庫中,開放給大家 免費學習使用

🎯 這裡奉上 📚Github 倉庫地址:https://github.com/xushanpei/Cesium_Study_Cases

CesiumJS 概述

CesiumJS 是一個用於顯示 三維地球地圖的開源 js 庫。支援 3D, 2.5D, 2D 形式的地圖展示,它可以用來顯示海量 三維模型資料、影像資料、地形高程資料、向量資料等等。同時也可以自行 繪製圖形高亮區域等,且支援絕大多數的瀏覽器和移動端

主要功能介紹

  • 使用 3d tiles 格式流式載入各種不同的 3d 資料,包含 傾斜攝影模型、三維建築物CADBIM 的外部和內部,點雲資料。並支援樣式配置和使用者互動操作。
  • 全球高精度 地形資料視覺化,支援地形誇張效果、以及可程式設計實現的 等高線坡度分析效果。
  • 支援多種資源的影象圖層,包括 WMSTMSWMTS 以及時序影象。影象支援透明度 疊加亮度對比度GAMMA色調飽和度都可以動態調整。
  • 支援標準的 向量格式 KMLGeoJSONTopoJSON、以及向量的 貼地效果。
  • 三維模型支援 gltf2.0 標準的 PRB 材質、動畫蒙皮變形效果。
  • 使用 CZML 支援動態時序資料的展示。
  • 支援各種幾何體:標註公告牌立方體球體橢圓體圓柱體走廊管徑牆體
  • 視覺化效果包括:基於太陽位置的 陰影自身陰影柔和陰影
  • 支援 大氣太陽陽光月亮星星水面
  • 粒子特效:火花
  • 地形模型3d tiles 模型的面裁剪。
  • 物件 點選地形點選
  • 支援滑鼠和觸控操作的 縮放渲染慣性平移飛行任意視角地形碰撞檢測
  • 支援 3d 地球、2d地圖、2.5d 哥倫布模式。3d 檢視可以使用透視和正視兩種投影方式。
  • 支援 標註公告牌的聚集效果。

基礎環境搭建

Vue3 環境搭建

首先確保你安裝了 Node.js(Node 安裝過程這裡不做過多講解,直接官網下載安裝即可),然後在 命令列執行以下命令:

sh npm init [email protected]latest

這一指令將會安裝並執行 create-vue,它是 Vue 官方的專案腳手架工具。你將會看到一些諸如 TypeScript測試支援之類的可選功能提示, 這裡按照個人需求安裝選擇對應的功能即可:

```sh ✔ Project name: … ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application development? … No / Yes ✔ Add Pinia for state management? … No / Yes ✔ Add Vitest for Unit testing? … No / Yes ✔ Add Cypress for both Unit and End-to-End testing? … No / Yes ✔ Add ESLint for code quality? … No / Yes ✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./... Done. ```

更多的專案配置以及使用教程,可以參考我之前的寫的文章:

🔥Vite2 + Vue3 + TypeScript + Pinia 搭建一套企業級的開發腳手架

🔥Vue3.x script setup 語法糖詳解,助力快速上手 Vue3.x

🔥 最詳細的 Vue3 + TypeScript 使用教程

安裝 Cesium

目前 Vite 專案下安裝 CesiumJS 有兩種方式:

  1. 直接到官方 下載原始碼引入到專案中使用
  2. npm 方式結合使用 Vite 外掛 vite-plugin-cesium 來安裝

下載原始碼安裝

開啟官網: https://www.cesium.com/ => Platform => CesiumJS

點選 下載,下載完成後 解壓,拷貝 Build 目錄下的 Cesium 下的所有內容到專案的 public 目錄下即可

入口檔案 index.html 中引入:

```html

```

npm 下載安裝

sh npm i cesium npm i -D vite-plugin-cesium

vite.config.ts 中配置:

```js import cesium from "vite-plugin-cesium"; // 引入外掛

export default defineConfig({ plugins: [cesium()], }); ```

以上兩種方式任選一種安裝即可,本次專案中的採用的是 第二種 npm 安裝的方式

讓 VScode 可以提示 Cesium 配置

sh npm i -S @types/cesium

好了,基礎的環境配置好了,下面來建立一個屬於自己的三維地球吧!!!

建立一個屬於自己的三維地球

申請 Token

在動手寫程式碼之前,記得先去 Cesium 申請一個 Token

Cesium 建議開發者在開發前申請一個單獨的 令牌(token),這個 Token 的作用是可以在 Cesium專案中呼叫 地圖地形服務。

開啟 https://cesium.com/ion 網址註冊登入自己的賬號

Access Tokens介面 Create token

給自己的 Token 定義一個名稱,然後根據自己的需求 勾選對應的功能即可

建立成功後複製 Token 儲存下來

這裡我直接在專案的資料夾下新建一個 utils 資料夾, 在 utils 資料夾下新建一個 Token.ts ,專門用來儲存我們的 Token

建立三維地球

1.在 src => view 目錄下建立一個 init.vue , 初始化出一個元件模板並且引入 Cesium

js import Cesium from "cesium";

引入成功後執行發現報錯了:

這個錯誤的大致意思是 cesium.js 沒有提供名為“default”的匯出, 解決方式有兩種:

  • 全量匯出,as 重新命名

js import * as Cesium from "cesium";

  • 直接 解構出需要的模組名稱, 不知道什麼是解構的建議看看 es6

js import { Viewer } from "cesium";

2.建立容器,初始化 Viewer

```JS import cesium from 'vite-plugin-cesium';

```

這樣一個簡單的 cesiumJS 三維數字地球就執行起來了

基礎要素講解

任何 Cesium 應用程式的基礎都是 ViewerViewer 是一個帶有多種功能的可互動的三維數字地球的容器,同時初始化介面也預設自帶了一些元件,其初始化場景及元件數字標號如下圖所示:

每一個元件的描述如下:

  1. Geocoder:查詢位置工具,查詢到之後會將鏡頭對準找到的地址
  2. HomeButton:首頁位置,點選之後將檢視跳轉到預設全球視角
  3. SceneModePicker:選擇視角的模式,3D,2D,2.5D 哥倫布檢視
  4. BaseLayerPicker:圖層選擇器,選擇要顯示的地圖服務和地形服務
  5. NavigationHelpButton:導航幫助按鈕,顯示預設的地圖控制幫助
  6. Animation:動畫器件,控制檢視動畫的播放速度
  7. CreditsDisplay:展示商標版權和資料歸屬
  8. Timeline:時間軸,指示當前時間,並允許使用者跳到特定的時間
  9. FullscreenButton:全屏按鈕

Viewer 中常用配置詳解如下:

JS viewer = new Cesium.Viewer("cesiumContainer", { animation: true, //是否建立動畫小器件,左下角儀表 baseLayerPicker: true, //是否顯示圖層選擇器 fullscreenButton: true, //是否顯示全屏按鈕 vrButton: true, // 用於切換 VR 模式的單個按鈕小部件。 geocoder: true, // //是否顯示geocoder小器件,右上角查詢按鈕 homeButton: true, //是否顯示Home按鈕 infoBox: true, //是否顯示資訊框 sceneModePicker: true, //是否顯示3D/2D選擇器 selectionIndicator: true, //是否顯示選取指示器元件 timeline: true, //是否顯示時間軸 navigationHelpButton: true, //是否顯示右上角的幫助按鈕 navigationInstructionsInitiallyVisible: true, scene3DOnly: false, //如果設定為true,則所有幾何圖形以3D模式繪製以節約GPU資源 shouldAnimate: false, // 初始化是否開始動畫 clockViewModel: undefined, // 一個檢視模型,它為使用者介面提供 Clock selectedImageryProviderViewModel: undefined, //當前影象圖層的顯示模型,僅baseLayerPicker設為true有意義 selectedTerrainProviderViewModel: undefined, //當前地形圖層的顯示模型,僅baseLayerPicker設為true有意義 skyAtmosphere: new Cesium.SkyAtmosphere(), // 圍繞提供的橢球體邊緣繪製的大氣 fullscreenElement: document.body, //全屏時渲染的HTML元素, useDefaultRenderLoop: true, //如果需要控制渲染迴圈,則設為true targetFrameRate: undefined, //使用預設render loop時的幀率 showRenderLoopErrors: false, //如果設為true,將在一個HTML面板中顯示錯誤資訊 automaticallyTrackDataSourceClocks: false, //自動追蹤最近新增的資料來源的時鐘設定 contextOptions: {}, //傳遞給Scene物件的上下文引數(scene.options) sceneMode: Cesium.SceneMode.SCENE3D, //初始場景模式 mapProjection: new Cesium.WebMercatorProjection(), //地圖投影體系 globe: undefined, // 在場景中渲染的地球儀,包括其地形 ( Globe#terrainProvider ) 和影象圖層 ( Globe#imageryLayers ) orderIndependentTranslucency: true, dataSources: new Cesium.DataSourceCollection(), //需要進行視覺化的資料來源的集合 projectionPicker: undefined, //ProjectionPicker 是用於在透視和正交投影之間切換的單按鈕小部件。 // imageryProviderViewModels: Cesium.createDefaultImageryProviderViewModels(), //圖層選擇器,可供BaseLayerPicker選擇的影象圖層ProviderViewModel陣列 // terrainProviderViewModels: Cesium.createDefaultTerrainProviderViewModels(), //地形選擇器,可供BaseLayerPicker選擇的地形圖層ProviderViewModel陣列 // imageryProvider: new Cesium.OpenStreetMapImageryProvider({ // credit: "", // url: "Custom url", // }), //影象圖層提供者,僅baseLayerPicker設為false有意義 terrainProvider: new Cesium.EllipsoidTerrainProvider(), //地形圖層提供者,僅baseLayerPicker設為false有意義 });

雖然 Cesium 自帶的一些元件功能都比較強大,但是奈何大多數情況下,我們都需要重寫這些元件來適配我們的專案, 所以很多時候都是把這些小元件隱藏起來

修改天空背景(skyBox)

Cesium 自帶的天空盒子背景偏黑色, 天空盒子的貼圖是6張(也叫立方體貼圖),分別對應6個方向的星空背景貼圖。

想象一下,一個立方體盒子將天球包圍,從球心到球面上任意一點的連線延伸出去必然與立方體盒子的一個相交,從而將球面上的一個點對映到立方體的一個面上。最終完整的天球對映到立方體盒子的兩個面上,形成6張正方形的圖片。

把提前準備好的天空盒圖片放到 /public/skyBox 資料夾下,Viewer 中增加如下配置即可:

JS //用於渲染星空的SkyBox物件 skyBox: new Cesium.SkyBox({ sources: { positiveX: "/skyBox/00h+00.jpg", negativeX: "skyBox/12h+00.jpg", positiveY: "/skyBox/06h+00.jpg", negativeY: "/skyBox/18h+00.jpg", positiveZ: "/skyBox/06h+90.jpg", negativeZ: "/skyBox/06h-90.jpg", }, })

效果如下展示:

去除版權資訊

js viewer.cesiumWidget.creditContainer.style.display = "none";

增加太陽光照效果

JS viewer.scene.globe.enableLighting = true;

實現晝夜聯動效果

```js // 載入晝夜聯動 const loadEarthAtNight = () => { const dynamicLighting = true; viewer.clock.multiplier = 4000; const imageryLayers = viewer.imageryLayers; const nightLayer = imageryLayers.get(0); const dayLayer = imageryLayers.addImageryProvider( new Cesium.IonImageryProvider({ assetId: 3845, }) );

imageryLayers.lowerToBottom(dayLayer); updateLighting(dynamicLighting, nightLayer, dayLayer); }; // 更新光照效果 const updateLighting = ( dynamicLighting: any, nightLayer: any, dayLayer: any ) => { dayLayer.show = dynamicLighting; viewer.scene.globe.enableLighting = dynamicLighting; viewer.clock.shouldAnimate = dynamicLighting; nightLayer.dayAlpha = dynamicLighting ? 1.0 : 1.0; }; ``` 程式碼片段

🎯 這篇文章是 Cesium 三維地球視覺化從入門到進階 專欄的開篇文章,主要是給一些沒有接觸過 Cesium 的並且想要入門三維視覺化的同學的一篇入門教程

🎯 在後續的文章中, 將會分享更多實踐案例,如果你也對 三維視覺化比較感興趣的話,歡迎關注我一起學習

🎯 Github 倉庫地址:https://github.com/xushanpei/Cesium_Study_Cases

寫在最後

公眾號前端開發愛好者 專注分享 web 前端相關技術文章影片教程資源、熱點資訊等,如果喜歡我的分享,給 🐟🐟 點一個 👍 或者 ➕關注 都是對我最大的支援。

大家好,我 xy,是一名前端 🤫 愛好:瞎折騰

如果你也是一名瞎折騰的前端歡迎加我微信交流哦...

🤫 一定要點我