入門:從環(huán)境搭建到數(shù)據(jù)可視化實(shí)戰(zhàn))
1. 項(xiàng)目概述從零構(gòu)建你的第一個(gè)三維地球最近幾年三維數(shù)字地球的應(yīng)用場(chǎng)景越來越廣從智慧城市、自然資源管理到氣象可視化、應(yīng)急指揮幾乎都能看到它的身影。如果你是一名GIS開發(fā)者、前端工程師或者是對(duì)空間數(shù)據(jù)可視化感興趣的技術(shù)愛好者那么CesiumJS絕對(duì)是你繞不開的一個(gè)名字。它不是一個(gè)簡(jiǎn)單的“地圖顯示庫(kù)”而是一個(gè)完整的、用于創(chuàng)建三維地理空間應(yīng)用的JavaScript平臺(tái)。簡(jiǎn)單來說有了Cesium你就能在瀏覽器里構(gòu)建出一個(gè)可以旋轉(zhuǎn)、縮放、加載各種數(shù)據(jù)影像、地形、模型、矢量的“活”地球。這個(gè)項(xiàng)目我們就從最基礎(chǔ)也是最關(guān)鍵的一步開始基于CesiumJS實(shí)現(xiàn)一個(gè)三維數(shù)字地球并完成從環(huán)境搭建到第一個(gè)地球顯示的完整入門流程。聽起來好像很高大上但其實(shí)只要跟著步驟走你會(huì)發(fā)現(xiàn)入門Cesium并沒有想象中那么復(fù)雜。整個(gè)過程不依賴復(fù)雜的后端純粹在前端完成非常適合新手快速上手感受三維GIS開發(fā)的魅力。無論你是想為自己的項(xiàng)目增加一個(gè)酷炫的全球視圖還是想深入學(xué)習(xí)WebGL和地理空間可視化這篇文章都將為你提供一個(gè)扎實(shí)的起點(diǎn)。2. 核心思路與技術(shù)選型解析2.1 為什么選擇CesiumJS在決定使用一個(gè)技術(shù)棧之前搞清楚“為什么是它”至關(guān)重要。市面上能做3D地圖的庫(kù)不少比如Mapbox GL JS、Three.js結(jié)合地圖插件等。CesiumJS的核心優(yōu)勢(shì)在于其“地理空間原生”的特性。首先CesiumJS內(nèi)置了對(duì)WGS84地理坐標(biāo)系的完整支持。這意味著你不需要自己處理經(jīng)緯度到三維空間坐標(biāo)的復(fù)雜轉(zhuǎn)換直接使用new Cesium.Cartographic(longitude, latitude, height)這樣的API即可。它原生理解什么是橢球體默認(rèn)使用WGS84橢球什么是地形什么是各種地理投影。這對(duì)于GIS應(yīng)用來說是基礎(chǔ)中的基礎(chǔ)如果自己用純3D引擎去實(shí)現(xiàn)會(huì)涉及大量底層數(shù)學(xué)計(jì)算。其次它提供了一整套地理空間數(shù)據(jù)加載與渲染的解決方案。這不僅僅是顯示一張圖片那么簡(jiǎn)單。Cesium可以無縫加載多種標(biāo)準(zhǔn)的影像服務(wù)如WMTS、WMS、TMS、地形數(shù)據(jù)如Cesium Ion提供的全球地形、自定義DEM、3D模型glTF/GLB、以及大量的矢量數(shù)據(jù)格式GeoJSON、KML、CZML。更強(qiáng)大的是它能處理時(shí)間動(dòng)態(tài)數(shù)據(jù)非常適合可視化衛(wèi)星軌跡、天氣變化等時(shí)序場(chǎng)景。最后性能與生態(tài)。CesiumJS基于WebGL在渲染大量數(shù)據(jù)如全球建筑白模、千萬級(jí)點(diǎn)數(shù)據(jù)時(shí)經(jīng)過了深度優(yōu)化。其背后的Cesium Ion平臺(tái)提供了豐富的現(xiàn)成數(shù)據(jù)源和3D Tiles流式傳輸服務(wù)雖然部分服務(wù)收費(fèi)但極大地降低了獲取和處理全球尺度數(shù)據(jù)的門檻。社區(qū)活躍文檔盡管中文文檔更新有時(shí)滯后和案例豐富遇到問題比較容易找到解決方案。2.2 項(xiàng)目整體架構(gòu)設(shè)計(jì)我們這個(gè)入門項(xiàng)目的目標(biāo)很明確在本地或一個(gè)簡(jiǎn)單的Web服務(wù)器環(huán)境下運(yùn)行起一個(gè)包含CesiumJS庫(kù)的HTML頁(yè)面并成功初始化一個(gè)三維地球視圖。其技術(shù)架構(gòu)非常簡(jiǎn)單清晰是一個(gè)典型的前端靜態(tài)應(yīng)用結(jié)構(gòu)依賴層核心是CesiumJS庫(kù)。我們將通過兩種主流方式獲取它使用CDN在線引入或者下載庫(kù)文件到本地進(jìn)行離線開發(fā)。應(yīng)用層一個(gè)HTML文件作為入口一個(gè)JavaScript文件編寫主要的邏輯代碼一個(gè)CSS文件進(jìn)行簡(jiǎn)單的樣式控制。數(shù)據(jù)/資源層Cesium運(yùn)行時(shí)需要加載一些資源比如默認(rèn)的藍(lán)色星空背景圖、水紋效果貼圖、控件圖標(biāo)等。這些資源通常位于Cesium庫(kù)的Build/Cesium/Assets和Build/Cesium/Widgets等目錄下。如果使用CDN這些資源會(huì)自動(dòng)從CDN加載如果本地部署則需要確保資源路徑正確。這種架構(gòu)的優(yōu)勢(shì)在于輕量、快速?zèng)]有任何后端依賴所有邏輯在瀏覽器中執(zhí)行非常適合學(xué)習(xí)、演示和快速原型開發(fā)。2.3 關(guān)鍵工具與資源準(zhǔn)備在開始寫代碼之前我們需要準(zhǔn)備好“工具箱”。對(duì)于純粹的Cesium前端開發(fā)你甚至不需要安裝Node.js或任何構(gòu)建工具。一個(gè)現(xiàn)代瀏覽器強(qiáng)烈推薦Chrome或Edge因其開發(fā)者工具對(duì)WebGL調(diào)試更友好和一個(gè)代碼編輯器如VS Code就足夠了。但是為了獲得更好的開發(fā)體驗(yàn)和未來項(xiàng)目擴(kuò)展的可能性我建議搭建一個(gè)簡(jiǎn)單的本地開發(fā)環(huán)境代碼編輯器VS Code安裝Live Server插件。這個(gè)插件可以一鍵啟動(dòng)一個(gè)本地HTTP服務(wù)器并支持熱重載。這對(duì)于需要加載本地資源文件的Cesium項(xiàng)目來說非常方便可以避免因file://協(xié)議引起的跨域問題。瀏覽器Chrome/Edge。務(wù)必開啟開發(fā)者工具我們將會(huì)頻繁使用到“Console”面板查看日志和錯(cuò)誤使用“Sources”面板調(diào)試代碼以及使用“Network”面板查看資源加載情況。Cesium庫(kù)文件我們將從Cesium官網(wǎng)下載穩(wěn)定版本的庫(kù)。訪問 Cesium官網(wǎng) 并點(diǎn)擊“Download CesiumJS”你會(huì)得到一個(gè)ZIP包。解壓后我們主要關(guān)注Build/Cesium目錄下的內(nèi)容。訪問令牌可選但推薦為了加載Cesium Ion提供的默認(rèn)底圖Bing Maps影像等和地形你需要一個(gè)免費(fèi)的Ion訪問令牌。去Cesium Ion官網(wǎng)注冊(cè)一個(gè)賬戶在“Access Tokens”頁(yè)面創(chuàng)建一個(gè)默認(rèn)令牌即可。這能讓你一開始就獲得漂亮的全球影像學(xué)習(xí)體驗(yàn)更好。注意使用Cesium Ion的默認(rèn)底圖需要網(wǎng)絡(luò)連接并且有配額限制免費(fèi)賬戶足夠個(gè)人學(xué)習(xí)使用。如果項(xiàng)目要求完全離線或內(nèi)網(wǎng)部署則需要準(zhǔn)備自己的離線影像和地形數(shù)據(jù)源這屬于進(jìn)階內(nèi)容本項(xiàng)目暫不涉及。3. 兩種入門安裝方式詳解萬事開頭難但Cesium的“開頭”提供了多種選擇。這里我詳細(xì)講解兩種最常用的方式CDN引入和本地庫(kù)引入。我會(huì)對(duì)比它們的優(yōu)劣并給出每一步的操作細(xì)節(jié)和原理。3.1 方式一CDN引入最快上手CDN內(nèi)容分發(fā)網(wǎng)絡(luò)引入是最簡(jiǎn)單、最快捷的方式特別適合快速驗(yàn)證、制作在線Demo或初學(xué)者體驗(yàn)。操作步驟創(chuàng)建項(xiàng)目文件夾在本地創(chuàng)建一個(gè)空文件夾例如cesium-earth-demo。創(chuàng)建HTML文件在該文件夾內(nèi)創(chuàng)建index.html。編寫HTML骨架在index.html中寫入基礎(chǔ)HTML5結(jié)構(gòu)。引入Cesium CSS在head標(biāo)簽內(nèi)通過CDN鏈接引入Cesium的樣式文件。這個(gè)文件定義了查看器控件如縮放按鈕、指南針的樣式。link hrefhttps://cesium.com/downloads/cesiumjs/releases/1.107/build/Cesium/Widgets/widgets.css relstylesheet引入Cesium JS在body標(biāo)簽的末尾或head中但使用async屬性引入Cesium的核心JavaScript庫(kù)。script srchttps://cesium.com/downloads/cesiumjs/releases/1.107/build/Cesium/Cesium.js/script提示請(qǐng)注意URL中的版本號(hào)1.107。你應(yīng)該始終從Cesium官網(wǎng)獲取最新穩(wěn)定版的CDN鏈接因?yàn)锳PI可能會(huì)有變動(dòng)。直接使用我例子中的鏈接可能在未來失效。創(chuàng)建容器和主腳本在body中創(chuàng)建一個(gè)全屏的div作為地球的容器并創(chuàng)建我們自己的JS文件main.js。body div idcesiumContainer stylewidth: 100%; height: 100vh; margin: 0; padding: 0;/div script src./main.js/script /body編寫初始化代碼在main.js中編寫初始化地球的代碼。// 設(shè)置Cesium.Ion.defaultAccessToken。如果你沒有令牌可以暫時(shí)注釋掉這行 // 但地球?qū)@示為默認(rèn)的瓦片灰色網(wǎng)格沒有影像和地形。 Cesium.Ion.defaultAccessToken 你的Ion訪問令牌; // 初始化Cesium Viewer將其掛載到id為‘cesiumContainer’的DOM元素上。 const viewer new Cesium.Viewer(cesiumContainer, { // 這里可以傳遞一系列配置選項(xiàng) // 例如使用OpenStreetMap影像無需token作為底圖替代方案 // imageryProvider: new Cesium.OpenStreetMapImageryProvider({ // url: https://a.tile.openstreetmap.org/ // }), // 禁用一些默認(rèn)控件以簡(jiǎn)化界面 // animation: false, // 時(shí)間軸動(dòng)畫控件 // baseLayerPicker: false, // 底圖選擇器 // fullscreenButton: false, // 全屏按鈕 // vrButton: false, // VR按鈕 // geocoder: false, // 搜索框 // homeButton: false, // 主頁(yè)按鈕 // infoBox: false, // 信息框 // sceneModePicker: false, // 2D/3D模式選擇器 // selectionIndicator: false, // 選擇指示器 // timeline: false, // 時(shí)間軸 // navigationHelpButton: false, // 導(dǎo)航幫助按鈕 }); // 你可以通過viewer對(duì)象進(jìn)行更多操作例如設(shè)置初始視角 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 15000000), // 北京上空1500公里 orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-90), // 視角垂直向下 roll: 0.0 } });CDN方式的優(yōu)缺點(diǎn)分析優(yōu)點(diǎn)無需下載數(shù)百M(fèi)B的庫(kù)文件設(shè)置極其簡(jiǎn)單總是使用最新或指定版本。缺點(diǎn)完全依賴外部網(wǎng)絡(luò)斷網(wǎng)無法工作無法進(jìn)行深度的源碼調(diào)試和定制加載速度受網(wǎng)絡(luò)影響。3.2 方式二本地庫(kù)引入推薦用于正式開發(fā)對(duì)于大多數(shù)嚴(yán)肅的學(xué)習(xí)和項(xiàng)目開發(fā)我強(qiáng)烈推薦使用本地庫(kù)的方式。它雖然第一步稍顯繁瑣但帶來了離線開發(fā)、源碼調(diào)試和構(gòu)建集成的可能性。操作步驟下載Cesium庫(kù)從官網(wǎng)下載ZIP包并解壓。假設(shè)你將解壓后的文件夾重命名為Cesium并放在你的項(xiàng)目根目錄下結(jié)構(gòu)如下cesium-earth-project/ ├── Cesium/ # 解壓后的Cesium庫(kù)目錄 │ ├── Build/ │ │ └── Cesium/ │ │ ├── Cesium.js │ │ ├── Widgets/ │ │ └── Assets/ │ └── Source/ ├── index.html ├── main.js └── style.css (可選)修改HTML中的引用路徑在index.html中將CDN鏈接替換為指向本地Cesium目錄的相對(duì)路徑。!-- 引入樣式 -- link href./Cesium/Build/Cesium/Widgets/widgets.css relstylesheet !-- 引入主庫(kù) -- script src./Cesium/Build/Cesium/Cesium.js/script解決資源路徑問題關(guān)鍵這是本地引入最容易出錯(cuò)的一步。Cesium在運(yùn)行時(shí)需要加載圖標(biāo)、圖片等靜態(tài)資源它默認(rèn)會(huì)從相對(duì)于Cesium.js文件的路徑去尋找Assets和Widgets目錄。如果你按照上面的結(jié)構(gòu)放置并且通過本地HTTP服務(wù)器如VS Code Live Server打開index.html那么路徑通常是正確的。 為了確保萬無一失你可以在初始化Viewer之前告訴Cesium資源的根路徑// 在main.js的最開始設(shè)置Cesium的資源基路徑 window.CESIUM_BASE_URL ./Cesium/Build/Cesium/; Cesium.Ion.defaultAccessToken 你的Ion訪問令牌; const viewer new Cesium.Viewer(cesiumContainer);設(shè)置CESIUM_BASE_URL全局變量是解決本地部署資源404錯(cuò)誤的最有效方法。使用本地HTTP服務(wù)器千萬不要直接雙擊index.html用file://協(xié)議打開。這會(huì)導(dǎo)致CORS跨域錯(cuò)誤因?yàn)闉g覽器禁止從file://協(xié)議加載許多類型的資源。務(wù)必使用一個(gè)本地HTTP服務(wù)器。VS Code用戶安裝“Live Server”插件然后在index.html文件上右鍵選擇“Open with Live Server”。命令行用戶如果你有Node.js可以在項(xiàng)目根目錄運(yùn)行npx serve或python -m http.server 8080。本地方式的優(yōu)缺點(diǎn)分析優(yōu)點(diǎn)完全離線可用可以深入Source目錄閱讀和調(diào)試源碼便于與Webpack、Vite等現(xiàn)代前端構(gòu)建工具集成資源加載穩(wěn)定快速。缺點(diǎn)首次需要下載較大的庫(kù)文件需要配置本地服務(wù)器項(xiàng)目結(jié)構(gòu)稍復(fù)雜。實(shí)操心得對(duì)于新手我建議先從CDN方式開始在5分鐘內(nèi)看到地球旋轉(zhuǎn)的效果獲得正反饋。當(dāng)你想深入學(xué)習(xí)開始編寫復(fù)雜功能時(shí)立刻切換到本地庫(kù)方式。你會(huì)經(jīng)常需要查看Cesium的源碼來理解某個(gè)對(duì)象或方法的細(xì)節(jié)本地環(huán)境是必不可少的。4. 第一個(gè)三維地球的深度配置與交互成功初始化一個(gè)地球只是開始。默認(rèn)的Viewer對(duì)象提供了豐富的可配置項(xiàng)和內(nèi)置功能理解它們能讓你更好地控制這個(gè)地球。4.1 Viewer 配置項(xiàng)詳解new Cesium.Viewer(containerId, options)的第二個(gè)參數(shù)是一個(gè)配置對(duì)象。下面是一些最常用且重要的配置項(xiàng)解析imageryProvider: 影像圖層提供器。這是決定地球“皮膚”的核心。如果不指定默認(rèn)使用Cesium Ion提供的Bing Maps影像需要Token。你可以替換為其他提供商const viewer new Cesium.Viewer(cesiumContainer, { imageryProvider: new Cesium.TileMapServiceImageryProvider({ url: Cesium.buildModuleUrl(Assets/Textures/NaturalEarthII) }), // 使用Cesium自帶的NaturalEarthII離線影像 // 或者使用ArcGIS全球影像 // imageryProvider: new Cesium.ArcGisMapServerImageryProvider({ // url: https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer // }), });terrainProvider: 地形提供器。讓地球表面不再是光滑的球體而是有起伏的真實(shí)地形。同樣默認(rèn)使用Cesium Ion地形需要Token。terrainProvider: Cesium.createWorldTerrain() // 創(chuàng)建全球地形skyBox: 天空盒即地球之外的星空背景。你可以禁用或自定義它。skyBox: false, // 禁用天空盒背景變?yōu)楹谏?// 或者使用自定義的星空?qǐng)D // skyBox: new Cesium.SkyBox({ // sources: { // positiveX: stars/px.jpg, // negativeX: stars/nx.jpg, // positiveY: stars/py.jpg, // negativeY: stars/ny.jpg, // positiveZ: stars/pz.jpg, // negativeZ: stars/nz.jpg // } // }),sceneMode: 初始場(chǎng)景模式。Cesium.SceneMode.SCENE3D是默認(rèn)的3D球體模式Cesium.SceneMode.SCENE2D是2D平面地圖模式Cesium.SceneMode.COLUMBUS_VIEW是2.5D的哥倫布視圖模式。fullscreenButton,vrButton,geocoder等這些布爾值選項(xiàng)控制界面右上角各個(gè)控件的顯示與隱藏。在上文的代碼注釋中已列出你可以根據(jù)需要設(shè)置為false來簡(jiǎn)化界面。4.2 操控相機(jī)設(shè)定你的觀察視角相機(jī)viewer.camera控制著我們觀察地球的位置和角度。掌握相機(jī)操作是進(jìn)行三維導(dǎo)航的基礎(chǔ)。設(shè)置初始視角camera.setView(options)是最常用的方法。destination可以是一個(gè)Cartesian3三維坐標(biāo)單位米也可以是一個(gè)Rectangle矩形區(qū)域。通常我們使用Cesium.Cartesian3.fromDegrees(lon, lat, height)來從經(jīng)緯度創(chuàng)建坐標(biāo)其中height是距離橢球體表面的高度米。// 飛到紐約上空1000米處并以45度俯角觀看 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(-74.0, 40.7, 1000.0), orientation: { heading: Cesium.Math.toRadians(0), // 北方向弧度制 pitch: Cesium.Math.toRadians(-45), // 俯角-90度垂直向下 roll: 0.0 // 翻滾角 } });相機(jī)動(dòng)畫飛行camera.flyTo(options)會(huì)生成一個(gè)平滑的動(dòng)畫過渡到目標(biāo)視角比setView的瞬間跳轉(zhuǎn)體驗(yàn)更好。其參數(shù)與setView類似但可以額外設(shè)置動(dòng)畫時(shí)長(zhǎng)duration、飛行路徑等。viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000), // 飛到北京上空5公里 duration: 3.0 // 飛行時(shí)間3秒 });實(shí)時(shí)監(jiān)聽相機(jī)變化你可以監(jiān)聽相機(jī)位置的變化用于實(shí)現(xiàn)一些交互邏輯比如根據(jù)視野范圍動(dòng)態(tài)加載數(shù)據(jù)。viewer.scene.postRender.addEventListener(function() { const position viewer.camera.positionCartographic; const height viewer.camera.positionCartographic.height; const lon Cesium.Math.toDegrees(position.longitude); const lat Cesium.Math.toDegrees(position.latitude); // console.log(經(jīng)度: ${lon.toFixed(4)}, 緯度: ${lat.toFixed(4)}, 高度: ${height.toFixed(0)}米); });注意事項(xiàng)postRender在每一幀渲染后都會(huì)觸發(fā)不要在此處執(zhí)行過于耗時(shí)的操作否則會(huì)影響性能。對(duì)于簡(jiǎn)單的日志輸出或狀態(tài)更新是沒問題的。4.3 添加基礎(chǔ)數(shù)據(jù)點(diǎn)、線、面與標(biāo)簽一個(gè)空蕩蕩的地球意義不大。Cesium提供了豐富的Primitive和EntityAPI來添加圖形。Entity是更高級(jí)的、數(shù)據(jù)驅(qū)動(dòng)的抽象易于使用Primitive是更底層的圖形原語(yǔ)性能更高但更復(fù)雜。入門階段我們先從Entity開始。添加一個(gè)點(diǎn)Billboardconst redPoint viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(116.4, 39.9), point: { pixelSize: 10, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 }, label: { // 可選的標(biāo)簽 text: 北京, font: 14pt Helvetica, style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 標(biāo)簽在點(diǎn)的下方 pixelOffset: new Cesium.Cartesian2(0, -20) // 像素偏移 } }); // 讓相機(jī)飛向這個(gè)點(diǎn) viewer.zoomTo(redPoint);添加一條線Polylineconst blueLine viewer.entities.add({ polyline: { positions: Cesium.Cartesian3.fromDegreesArray([ 116.4, 39.9, // 北京 121.5, 31.2 // 上海 ]), width: 5, material: Cesium.Color.BLUE } });添加一個(gè)多邊形Polygonconst greenPolygon viewer.entities.add({ polygon: { hierarchy: Cesium.Cartesian3.fromDegreesArray([ 115.0, 40.0, 117.0, 40.0, 117.0, 38.5, 115.0, 38.5 ]), material: Cesium.Color.GREEN.withAlpha(0.5), // 半透明綠色 outline: true, outlineColor: Cesium.Color.BLACK } });添加一個(gè)3D模型glTFconst modelEntity viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100), // 北京上空100米 model: { uri: ./path/to/your/model.gltf, // 指向你的glTF模型文件 scale: 10.0 // 縮放比例 } });通過這些簡(jiǎn)單的Entity操作你已經(jīng)可以在三維地球上標(biāo)注位置、繪制路徑、劃定區(qū)域甚至放置建筑模型了。viewer.entities是一個(gè)EntityCollection你可以通過add、remove、removeAll等方法動(dòng)態(tài)管理所有實(shí)體。5. 開發(fā)環(huán)境搭建與工程化實(shí)踐當(dāng)你完成了第一個(gè)Demo想要開始一個(gè)更正式的項(xiàng)目時(shí)將Cesium集成到現(xiàn)代前端工程化工作流中就變得很重要了。這能讓你享受模塊化、熱更新、代碼壓縮等便利。5.1 使用npm/yarn安裝Cesium這是管理Cesium依賴最規(guī)范的方式。在你的項(xiàng)目根目錄下執(zhí)行npm install cesium # 或 yarn add cesium安裝后Cesium庫(kù)文件會(huì)位于node_modules/cesium/Build/Cesium目錄下。5.2 在Webpack/Vite項(xiàng)目中集成Webpack配置要點(diǎn)復(fù)制靜態(tài)資源Cesium的Workers和Assets等資源需要被復(fù)制到最終構(gòu)建的輸出目錄??梢允褂肅opyWebpackPlugin。// webpack.config.js const path require(path); const CopyWebpackPlugin require(copy-webpack-plugin); const CesiumSource node_modules/cesium/Source; const CesiumWorkers ../Build/Cesium/Workers; module.exports { // ... 其他配置 plugins: [ new CopyWebpackPlugin({ patterns: [ { from: path.join(CesiumSource, CesiumWorkers), to: Workers }, { from: path.join(CesiumSource, Assets), to: Assets }, { from: path.join(CesiumSource, Widgets), to: Widgets }, { from: path.join(CesiumSource, ThirdParty), to: ThirdParty }, ], }), ], // 告訴Webpack哪些模塊是Cesium需要的AMD風(fēng)格模塊不需要解析 amd: { toUrlUndefined: true }, // 解決Cesium多線程Worker的加載問題 node: { // Resolve node module use of fs fs: empty } };設(shè)置CESIUM_BASE_URL在你的主入口JS文件中需要根據(jù)環(huán)境設(shè)置資源基礎(chǔ)路徑。// main.js import * as Cesium from cesium; import cesium/Build/Cesium/Widgets/widgets.css; // 重要設(shè)置Cesium靜態(tài)資源的基礎(chǔ)路徑 window.CESIUM_BASE_URL /; // 假設(shè)資源被復(fù)制到了輸出根目錄 Cesium.Ion.defaultAccessToken your_token; const viewer new Cesium.Viewer(cesiumContainer);Vite配置要點(diǎn)更簡(jiǎn)單Vite對(duì)靜態(tài)資源的處理更友好。安裝cesium后直接在組件或入口文件中引入即可。安裝vite-plugin-cesium社區(qū)插件非官方但很好用可以簡(jiǎn)化流程。npm install vite-plugin-cesium -D在vite.config.js中配置import { defineConfig } from vite; import cesium from vite-plugin-cesium; export default defineConfig({ plugins: [cesium()] });在Vue/React組件中直接使用// Vue組件示例 template div idcesiumContainer stylewidth: 100vw; height: 100vh;/div /template script setup import { onMounted } from vue; import * as Cesium from cesium; import cesium/Build/Cesium/Widgets/widgets.css; onMounted(() { Cesium.Ion.defaultAccessToken your_token; const viewer new Cesium.Viewer(cesiumContainer); // ... 你的代碼 }); /scriptVite插件會(huì)自動(dòng)處理CESIUM_BASE_URL和靜態(tài)資源的服務(wù)。5.3 性能優(yōu)化初步考量即使是入門項(xiàng)目也需要有性能意識(shí)因?yàn)槿S渲染非常消耗資源。按需加載數(shù)據(jù)不要一次性加載全球的高精度數(shù)據(jù)。使用Cesium.Cesium3DTileset加載3D Tiles數(shù)據(jù)時(shí)它會(huì)自動(dòng)根據(jù)視錐體裁剪和細(xì)節(jié)層次LOD進(jìn)行流式加載。控制實(shí)體數(shù)量對(duì)于大量靜態(tài)的點(diǎn)如成千上萬個(gè)傳感器使用Cesium.PointPrimitiveCollection或自定義的PrimitiveAPI會(huì)比創(chuàng)建同樣數(shù)量的Entity性能高得多。使用Web WorkersCesium默認(rèn)使用Web Workers進(jìn)行地形和影像瓦片的解碼不要禁用這個(gè)特性。監(jiān)控幀率在開發(fā)過程中可以開啟瀏覽器的性能監(jiān)視器或使用viewer.scene.debugShowFramesPerSecond true;在畫面上顯示實(shí)時(shí)幀率。保持幀率在60FPS左右為佳低于30FPS就需要考慮優(yōu)化了。6. 常見問題與排查技巧實(shí)錄在實(shí)際操作中你幾乎一定會(huì)遇到下面這些問題。這里我把它們和解決方案整理出來你可以像查字典一樣使用。6.1 地球一片黑或顯示網(wǎng)格現(xiàn)象地球不顯示影像只是一個(gè)黑色球體或灰色瓦片網(wǎng)格。可能原因及解決未設(shè)置或Ion Token錯(cuò)誤這是最常見的原因。檢查控制臺(tái)Console是否有關(guān)于Ion認(rèn)證的錯(cuò)誤信息。確保Cesium.Ion.defaultAccessToken已正確設(shè)置并且該Token在Cesium Ion賬戶中有效且未過期。網(wǎng)絡(luò)問題CDN鏈接失效或本地服務(wù)器無法訪問Cesium Ion服務(wù)。嘗試使用不需要Token的離線影像作為測(cè)試如TileMapServiceImageryProvider見3.1節(jié)代碼。資源路徑錯(cuò)誤僅限本地部署控制臺(tái)出現(xiàn)大量404錯(cuò)誤找不到Workers、Assets下的文件。務(wù)必檢查并正確設(shè)置window.CESIUM_BASE_URL并確保通過HTTP服務(wù)器訪問頁(yè)面。6.2 控制臺(tái)報(bào)錯(cuò) “Cesium is not defined”現(xiàn)象瀏覽器控制臺(tái)出現(xiàn)此錯(cuò)誤地球無法初始化??赡茉蚣敖鉀Q腳本加載順序問題在你自己調(diào)用Cesium對(duì)象的腳本執(zhí)行時(shí)Cesium.js庫(kù)還沒有加載完成。確保你的script srcmain.js標(biāo)簽放在引入Cesium.js的標(biāo)簽之后。模塊化引入問題如果你使用import * as Cesium from cesium;的方式確保你的構(gòu)建工具Webpack/Vite已正確配置并且cesium包已安裝。6.3 本地運(yùn)行出現(xiàn)CORS跨域錯(cuò)誤現(xiàn)象控制臺(tái)提示跨域請(qǐng)求被阻止通常發(fā)生在直接雙擊打開index.htmlfile://協(xié)議時(shí)。解決永遠(yuǎn)不要使用file://協(xié)議。必須使用本地HTTP服務(wù)器。使用VS Code Live Server、http-server、serve或任何你熟悉的靜態(tài)服務(wù)器工具。6.4 添加的實(shí)體Entity不顯示現(xiàn)象代碼執(zhí)行了viewer.entities.add(...)但地圖上什么也沒出現(xiàn)。排查步驟檢查坐標(biāo)確認(rèn)你提供的經(jīng)緯度坐標(biāo)在地球范圍內(nèi)經(jīng)度-180到180緯度-90到90。一個(gè)常見的錯(cuò)誤是經(jīng)緯度參數(shù)順序弄反Cesium通常是經(jīng)度, 緯度。檢查高度如果height值設(shè)置得非常大如默認(rèn)0而你的點(diǎn)沒有設(shè)置pixelSize或billboard它可能只是一個(gè)無限小的點(diǎn)在遠(yuǎn)處看不見。確保設(shè)置了point.pixelSize或使用billboard。檢查控制臺(tái)錯(cuò)誤實(shí)體定義可能有語(yǔ)法錯(cuò)誤查看控制臺(tái)是否有JS報(bào)錯(cuò)。使用zoomTo調(diào)用viewer.zoomTo(entity)或viewer.zoomTo(viewer.entities)讓相機(jī)飛到實(shí)體所在位置??赡軐?shí)體已經(jīng)添加只是不在當(dāng)前視野內(nèi)。6.5 界面控件或樣式錯(cuò)亂現(xiàn)象按鈕位置不對(duì)或控件樣式丟失??赡茉驔]有正確引入Cesium的CSS文件widgets.css。檢查HTML中l(wèi)ink標(biāo)簽的路徑是否正確以及是否在Cesium.js之前引入。6.6 性能緩慢頁(yè)面卡頓現(xiàn)象操作地球時(shí)感覺不流暢幀率很低。初步優(yōu)化降低地形細(xì)節(jié)如果使用了高精度地形可以嘗試暫時(shí)禁用地形viewer.terrainProvider Cesium.EllipsoidTerrainProvider();看看是否改善。簡(jiǎn)化影像圖層嘗試使用低分辨率的影像底圖。減少實(shí)體數(shù)量檢查是否在循環(huán)中添加了過多實(shí)體。對(duì)于大量點(diǎn)考慮使用PointPrimitiveCollection。關(guān)閉后期處理默認(rèn)的Viewer可能會(huì)開啟一些效果可以嘗試在創(chuàng)建時(shí)配置fxaa: false禁用抗鋸齒等。利用瀏覽器開發(fā)者工具的Performance面板進(jìn)行分析找到性能瓶頸。6.7 如何加載自定義離線數(shù)據(jù)這是一個(gè)進(jìn)階但常見的問題。Cesium加載離線數(shù)據(jù)的關(guān)鍵在于正確配置ImageryProvider或TerrainProvider的URL使其指向你的本地服務(wù)器上的瓦片目錄。離線影像將你的瓦片數(shù)據(jù)如TMS或WMTS格式組織好然后使用new Cesium.TileMapServiceImageryProvider({ url: ‘./your_tiles’ })。url指向包含layer.json或tilemapresource.xml的目錄。離線地形地形數(shù)據(jù)通常需要預(yù)處理成quantized-mesh格式。你可以使用Cesium官方工具CesiumTerrainBuilder或第三方工具如GDAL來生成。然后使用new Cesium.CesiumTerrainProvider({ url: ‘./your_terrain_tiles’ })加載。踩過這些坑之后你會(huì)發(fā)現(xiàn)Cesium的入門路徑其實(shí)非常清晰。從環(huán)境搭建到顯示地球再到添加數(shù)據(jù)和集成到工程化項(xiàng)目每一步都有跡可循。關(guān)鍵在于動(dòng)手實(shí)踐多寫代碼多查文檔英文官方文檔是最權(quán)威的多利用瀏覽器的開發(fā)者工具進(jìn)行調(diào)試。當(dāng)你成功地在自己的網(wǎng)頁(yè)上讓地球旋轉(zhuǎn)起來并放上第一個(gè)標(biāo)記點(diǎn)時(shí)那種成就感就是學(xué)習(xí)技術(shù)最好的動(dòng)力。