?
目錄
?
?前言
一、功能背景
1.1 核心功能概覽
1.2 技術棧與工具
二、車輛動畫
2.1 模型坐標
2.2 組合渲染
2.3 顯隱狀態
2.4 模型文件
三、雷達動畫
3.1 創建元素
3.2 動畫解析
3.3?坐標聯動
3.4?交互事件
四、完整代碼
4.1 屬性參數
4.2 邏輯代碼
加載車輛動畫
控制車輛動畫
加載雷達動畫
控制雷達動畫
4.3 模擬展示
五、注意事項
5.1 資源加載與路徑問題
5.2 性能與內存管理
5.3 兼容性與調試
六、本文總結
七、更多操作
?
?
?前言
在《Cesium 7,在 Cesium 上實現高速道路渲染》中,我們完成了高速道路的三維建模與場景搭建。本文作為續篇,將聚焦于動態元素與交互邏輯的開發,在已構建的道路場景中疊加雷達動畫與車輛模型,實現 “靜態場景 + 動態實體” 的完整可視化方案。通過本文分享,你將學會如何在 Cesium 道路場景中集成動態交互元素,并掌握坐標轉換、動畫控制與狀態管理的核心技術。
?
一、功能背景
功能實現效果與技術架構
1.1 核心功能概覽
- 車輛模型系統:加載 GLB 格式 3D 車輛模型,附帶標簽文本與動態擴散波紋,模擬救援車輛的實時位置。
- 雷達動畫系統:基于 HTML+CSS 實現圓形波紋擴散效果,綁定經緯度坐標,支持點擊交互觸發事件彈窗。
- 交互控制:通過統一接口切換元素顯隱狀態,結合 Cesium 坐標轉換實現動畫元素與地圖視圖的動態聯動。
1.2 技術棧與工具
- 框架:CesiumJS(三維渲染引擎)、JavaScript(邏輯控制)。
- 資源格式:GLB(3D 模型)、CSS3(動畫樣式)。
- 關鍵 API:
Cesium.Cartesian3.fromDegrees
:經緯度轉笛卡爾坐標。viewer.entities.add
:添加模型、標簽、波紋等實體。CallbackProperty
:動態更新橢圓波紋的半徑與透明度。
?
?
二、車輛動畫
車輛模型動畫開發詳解
2.1 模型坐標
模型加載與坐標計算
代碼實現
loadVehicleModelAnime() {// 初始經緯度(車輛位置)const initLng = this.RealCarLonLat.lon;const initLat = this.RealCarLonLat.lat;// 移動距離與地球半徑(用于坐標偏移計算)const moveDistance = 20; // 20米const earthRadius = 6371000; // 地球半徑(米)// 計算偏移量(簡化版航向角為0°,僅水平移動)const deltaLat = (moveDistance / earthRadius) * Math.cos(0);const deltaLng = (moveDistance / (earthRadius * Math.cos(Cesium.Math.toRadians(initLat)))) * Math.sin(0);const newLat = initLat + Cesium.Math.toDegrees(deltaLat);const newLng = initLng + Cesium.Math.toDegrees(deltaLng);// 目標位置(笛卡爾坐標)const targetPosition = Cesium.Cartesian3.fromDegrees(newLng, newLat, 0);// ... 后續模型實體創建代碼
}
原理說明
- 坐標偏移邏輯:通過球面幾何公式計算車輛在平面地圖上的偏移量,
deltaLat
?和?deltaLng
?分別對應緯度和經度方向的位移弧度,最終轉換為度數生成目標坐標。 - 航向角擴展:若需車輛朝向動態變化,可將?
heading
?參數與車輛實時航向數據綁定(如?vehicleHeading
),通過?HeadingPitchRollQuaternion
?動態更新模型朝向。
2.2 組合渲染
多實體組合渲染
組件拆解
實體類型 | 技術實現 | 關鍵屬性 / 配置 |
---|---|---|
車輛模型 | viewer.entities.add ?+?model ?屬性 | uri: "/glb/8jc.glb" ,scale: 1 |
標簽文本 | label ?實體 | 紅色填充 + 白色描邊,pixelOffset: [0, -30] |
擴散波紋 | 3 層?ellipse ?實體,通過?CallbackProperty ?動態更新半徑與透明度 | semiMajorAxis /semiMinorAxis ?隨時間線性增長 |
波紋動畫核心代碼
for (let i = 0; i < waveCount; i++) {const startTime = Date.now() + i * waveInterval; // 每層波紋延遲1秒啟動const waveEntity = viewer.entities.add({position: targetPosition,ellipse: {semiMajorAxis: new Cesium.CallbackProperty(() => {const elapsed = (Date.now() - startTime) % (waveCount * waveInterval);return 10 + 2000 * (elapsed / (waveCount * waveInterval)); // 從10米擴展到2010米}, false),material: new Cesium.ColorMaterialProperty(new Cesium.CallbackProperty(() => {const alpha = 1.0 - (Date.now() - startTime) / (waveCount * waveInterval);return Cesium.Color.RED.withAlpha(Math.max(0, alpha)); // 透明度線性衰減}, false))}});
}
2.3 顯隱狀態
顯隱狀態統一管理
toggleVehicleShowStatus() {if (!this.vehicleEntities || this.vehicleEntities.length === 0) return;this.vehicleVisible = !this.vehicleVisible;// 批量更新所有實體狀態this.vehicleEntities.forEach(entity => {entity.show = this.vehicleVisible;});
}
- 設計模式:采用「實體數組管理」模式,將模型、標簽、波紋實體存入?
vehicleEntities
?數組,通過統一接口批量操作顯隱狀態,避免重復代碼。 - 性能優化:隱藏時自動停止?
CallbackProperty
?的動態計算,減少無用渲染消耗。
2.4 模型文件
場景中加載的3D車輛模型文件,glb格式文件,見文章頂部。
?
?
三、雷達動畫
雷達動畫開發與交互邏輯
雷達動畫通過?HTML DOM 元素與?CSS3 關鍵幀動畫實現,具備輕量化、高性能的特點,可動態錨定地圖坐標并響應用戶交互。以下是基于代碼的詳細解析:
3.1 創建元素
基于 JavaScript 創建雷達容器與動畫元素
實現方式:通過?document.createElement
?動態創建 HTML 元素,避免直接操作靜態 DOM,提升代碼動態性與可維護性。
DOM 結構生成邏輯
// 創建雷達容器(圓形定位容器)
const container = document.createElement("div");
container.className = "radar_container"; // 關聯CSS類
container.style.width = "200px";
container.style.height = "200px";
container.style.borderRadius = "50%"; // 圓形外觀
container.style.position = "absolute"; // 絕對定位,基于地圖視口坐標
container.style.zIndex = "999"; // 層級置頂,避免被地圖覆蓋
信息提示文本
const tip = document.createElement("div");
tip.innerText = `求助點位置:${this.realEventList.begMileageNo} - ${this.realEventList.endMileageNo}`;
tip.style.position = "absolute";
tip.style.bottom = "70%"; // 位于容器頂部
tip.style.left = "50%";
tip.style.transform = "translateX(-50%)"; // 水平居中
tip.style.color = "red";
tip.style.pointerEvents = "none"; // 允許鼠標事件穿透到地圖
實現效果,提示文本固定在雷達容器正上方,顯示事件位置信息,支持動態數據綁定(如?realEventList
)。
雷達波紋元素
for (let i = 0; i < 3; i++) {const wave = document.createElement("div");wave.className = "radar_wave"; // 關聯CSS類// 基礎樣式:圓形邊框+陰影wave.style.width = "20px";wave.style.height = "20px";wave.style.border = "1px solid red";wave.style.borderRadius = "50%";wave.style.boxShadow = "inset 0 0 5px 1px red"; // 內陰影增強立體感// 定位與動畫設置wave.style.top = "50%";wave.style.left = "50%";wave.style.transformOrigin = "center center"; // 動畫中心點wave.style.animation = `radar_wave-animation 3s infinite`; // 引用關鍵幀動畫wave.style.animationDelay = `${i}s`; // 延遲啟動(0s/1s/2s),形成層次感
}
3.2 動畫解析
CSS 關鍵幀動畫解析
動畫定義方式:通過 JavaScript 動態向?head
?標簽注入?<style>
?標簽,避免全局樣式污染。
if (!document.getElementById("radar-wave-style")) {const style = document.createElement("style");style.id = "radar-wave-style";style.innerHTML = `@keyframes radar_wave-animation {0% {transform: translate(-50%, -50%) scale(0); /* 初始狀態:縮放為0,位于容器中心 */opacity: 1; /* 完全不透明 */}100% {transform: translate(-50%, -50%) scale(6); /* 最終狀態:縮放6倍,覆蓋容器范圍 */opacity: 0; /* 完全透明 */}}`;document.head.appendChild(style);
}
核心參數說明:
屬性 | 作用描述 |
---|---|
transform: scale() | 控制波紋半徑擴展,scale(6) ?表示從初始尺寸(20px)擴展至 120px(覆蓋 200px 容器)。 |
opacity | 實現波紋漸隱效果,避免動畫結束后殘留視覺痕跡。 |
animationDelay | 每層波紋延遲啟動,形成 “多層擴散” 的動態層次感(如第 1 層 0s 啟動,第 2 層 1s 啟動)。 |
3.3?坐標聯動
地圖坐標與屏幕坐標聯動
toggleRadarShowStatus() {if (this.radarVisible) {// 初始化坐標轉換this.radarPosition = Cesium.Cartesian3.fromDegrees(this.radarLonLat.lon, this.radarLonLat.lat);const canvasPos = viewer.scene.cartesianToCanvasCoordinates(this.radarPosition);// 定位DOM元素this.radarOverlayDom.style.left = `${canvasPos.x - 100}px`; // 水平居中(容器寬200px)this.radarOverlayDom.style.top = `${canvasPos.y - 100}px`; // 垂直居中// 每幀更新位置(監聽場景預渲染事件)this.updateRadarPositionHandler = viewer.scene.preRender.addEventListener(() => {const pos = viewer.scene.cartesianToCanvasCoordinates(this.radarPosition);this.radarOverlayDom.style.left = `${pos.x - 100}px`;this.radarOverlayDom.style.top = `${pos.y - 100}px`;});} else {// 隱藏時移除監聽if (this.updateRadarPositionHandler) {viewer.scene.preRender.removeEventListener(this.updateRadarPositionHandler);this.updateRadarPositionHandler = null;}}
}
核心邏輯,通過?cartesianToCanvasCoordinates
?將 Cesium 三維坐標轉換為瀏覽器視口坐標,確保雷達容器始終錨定在地圖指定位置,支持地圖縮放、平移時的實時跟隨。
3.4?交互事件
交互事件與信息展示
// 點擊雷達觸發事件彈窗
container.addEventListener("click", () => {this.EventDialogVisible = true; // 顯示Vue彈窗組件
});// 提示文本動態更新(示例)
const tip = document.createElement("div");
tip.innerText = `求助點坐標:${this.realEventList.begMileageNo} - ${this.realEventList.endMileageNo}`;
交互擴展,可結合 Vue/React 等前端框架實現彈窗數據綁定,展示事件詳情(如救援進度、預計到達時間)。
?
?
四、完整代碼
4.1 屬性參數
// 雷達位置的經緯度坐標(地理坐標系)radarLonLat: {lon: 117.610995,lat: 34.399076,},// 雷達動畫顯示狀態控制radarVisible: false,// 雷達動畫的DOM容器引用(用于操作HTML元素)radarOverlayDom: null,// 雷達在Cesium中的三維坐標(笛卡爾坐標系)radarPosition: null,// 雷達位置更新事件句柄(用于綁定/移除渲染循環監聽)updateRadarPositionHandler: null,// 實際事件數據(存儲救援相關信息)// 救援車輛的初始經緯度坐標(地理坐標系)RealCarLonLat: {lon: 117.617227,lat: 34.324461,},
4.2 邏輯代碼
加載車輛動畫
//? 加載車輛動畫,默認隱藏loadVehicleModelAnime() {// 獲取初始經緯度坐標const initLng = this.RealCarLonLat.lon;const initLat = this.RealCarLonLat.lat;// 車輛移動距離(米)const moveDistance = 20;// 地球半徑(米)const earthRadius = 6371000;// 初始朝向(0表示正北方向)const heading = 0;// 計算經緯度變化量(基于球面幾何)let deltaLat = (moveDistance / earthRadius) * Math.cos(heading);let deltaLng = (moveDistance / (earthRadius * Math.cos(this.Cesium.Math.toRadians(initLat)))) * Math.sin(heading);// 轉換為度數let newLat = initLat + this.Cesium.Math.toDegrees(deltaLat);let newLng = initLng + this.Cesium.Math.toDegrees(deltaLng);// 創建目標位置(Cartesian3坐標)const targetPosition = this.Cesium.Cartesian3.fromDegrees(newLng, newLat, 0);// 初始化車輛實體數組this.vehicleEntities = [];// 初始狀態為隱藏this.vehicleVisible = false;// 模型實體 - 加載3D車輛模型const vehicleModel = this.viewer.entities.add({name: "車輛模型",position: targetPosition,model: {uri: "/glb/8jc.glb", // 模型文件路徑scale: 1, // 初始縮放比例minimumPixelSize: 20, // 最小像素尺寸maximumScale: 40, // 最大縮放比例},// 設置模型朝向(航向角、俯仰角、滾轉角)orientation: this.Cesium.Transforms.headingPitchRollQuaternion(targetPosition,new this.Cesium.HeadingPitchRoll(this.Cesium.Math.toRadians(-170), // 航向角(-170度)this.Cesium.Math.toRadians(0), // 俯仰角(0度)this.Cesium.Math.toRadians(0) // 滾轉角(0度))),show: false // 初始不顯示});this.vehicleEntities.push(vehicleModel);// 標簽實體 - 顯示車輛名稱const labelEntity = this.viewer.entities.add({position: targetPosition,label: {text: "拯救車", // 標簽文字font: "14px sans-serif", // 字體樣式fillColor: this.Cesium.Color.RED, // 文字顏色outlineColor: this.Cesium.Color.WHITE, // 文字輪廓顏色outlineWidth: 1, // 輪廓寬度style: this.Cesium.LabelStyle.FILL_AND_OUTLINE, // 填充加輪廓樣式verticalOrigin: this.Cesium.VerticalOrigin.BOTTOM, // 文字垂直對齊底部pixelOffset: new this.Cesium.Cartesian2(0, -30), // 文字偏移量(向上偏移30像素)disableDepthTestDistance: Number.POSITIVE_INFINITY // 禁用深度測試},show: false // 初始不顯示});this.vehicleEntities.push(labelEntity);// 動態擴散波紋效果 - 創建多個波紋實體const waveCount = 3; // 波紋數量const waveInterval = 1000; // 波紋生成間隔(毫秒)for (let i = 0; i < waveCount; i++) {// 計算每個波紋的開始時間const startTime = Date.now() + i * waveInterval;const waveEntity = this.viewer.entities.add({position: targetPosition,ellipse: {// 動態橢圓長軸(隨時間變化)semiMajorAxis: new this.Cesium.CallbackProperty(() => {let elapsed = (Date.now() - startTime) % (waveCount * waveInterval);let scale = elapsed / (waveCount * waveInterval);return 10 + 2000 * scale; // 從10米逐漸擴大到2010米}, false),// 動態橢圓短軸(隨時間變化)semiMinorAxis: new this.Cesium.CallbackProperty(() => {let elapsed = (Date.now() - startTime) % (waveCount * waveInterval);let scale = elapsed / (waveCount * waveInterval);return 10 + 2000 * scale; // 從10米逐漸擴大到2010米}, false),// 動態顏色(透明度隨時間變化)material: new this.Cesium.ColorMaterialProperty(new this.Cesium.CallbackProperty(() => {let elapsed = (Date.now() - startTime) % (waveCount * waveInterval);let alpha = 1.0 - elapsed / (waveCount * waveInterval); // 從完全不透明到完全透明return this.Cesium.Color.RED.withAlpha(alpha); // 紅色漸變}, false)),height: 0, // 高度為0(貼地)outline: false, // 無輪廓classificationType: this.Cesium.ClassificationType.BOTH, // 貼地顯示},show: false // 初始不顯示});this.vehicleEntities.push(waveEntity);}},
控制車輛動畫
// 控制車輛動畫顯示/隱藏狀態toggleVehicleShowStatus() {// 如果實體數組不存在或為空,則直接返回if (!this.vehicleEntities || this.vehicleEntities.length === 0) return;// 切換顯示狀態this.vehicleVisible = !this.vehicleVisible;// 遍歷所有車輛相關實體,統一設置顯示狀態this.vehicleEntities.forEach(entity => {entity.show = this.vehicleVisible;});},
這里的 loadVehicleModelAnime函數 用來創建車輛動畫,默認隱藏;toggleVehicleShowStatus函數 用來控制車輛動畫,首次執行,顯示車輛動畫,再次執行,隱藏車輛動畫,循環往復。
加載雷達動畫
//? 創建雷達動畫,默認隱藏loadRadarLocationAnime() {// 如果雷達DOM已存在,則直接返回(避免重復創建)if (this.radarOverlayDom) return;// 創建雷達容器div(圓形居中布局)const container = document.createElement("div");container.className = "radar_container";// 設置樣式container.style.position = "absolute"; // 絕對定位container.style.width = "200px"; // 寬度container.style.height = "200px"; // 高度container.style.borderRadius = "50%"; // 圓形container.style.overflow = "visible"; // 允許內容溢出(顯示提示文字)container.style.pointerEvents = "auto"; // 允許鼠標事件container.style.zIndex = "999"; // 置于頂層container.style.display = "flex"; // 彈性布局container.style.alignItems = "center"; // 垂直居中container.style.justifyContent = "center"; // 水平居中container.style.cursor = "pointer"; // 鼠標懸停顯示手型container.style.margin = "auto"; // 自動外邊距container.style.border = "2px solid transparent"; // 默認透明邊框// 創建提示文字元素const tip = document.createElement("div");tip.innerText = `求助點位置:${this.realEventList.begMileageNo} - ${this.realEventList.endMileageNo}`; // 顯示求助點位置信息tip.style.textShadow = "2px 3px 1px black"; // 文字陰影效果tip.style.position = "absolute"; // 絕對定位tip.style.bottom = "70%"; // 放在容器底部上方tip.style.left = "50%"; // 水平居中tip.style.transform = "translateX(-50%)"; // 水平居中修正tip.style.padding = "2px 6px"; // 內邊距tip.style.font = "14pt"; // 字體大小tip.style.color = "red"; // 文字顏色tip.style.borderRadius = "4px"; // 圓角邊框tip.style.whiteSpace = "nowrap"; // 禁止換行tip.style.pointerEvents = "none"; // 不影響鼠標事件tip.style.userSelect = "none"; // 禁止文字選中tip.style.opacity = "1"; // 初始完全不透明tip.style.transition = "opacity 0.3s ease"; // 透明度過渡效果container.appendChild(tip); // 將提示文字添加到容器中// 添加點擊事件(點擊雷達顯示事件詳情對話框)container.addEventListener("click", () => {this.EventDialogVisible = true;});// 添加CSS關鍵幀動畫樣式(頁面只添加一次)if (!document.getElementById("radar-wave-style")) {const style = document.createElement("style");style.id = "radar-wave-style";style.innerHTML = `@keyframes radar_wave-animation {0% {transform: translate(-50%, -50%) scale(0); // 初始狀態:縮小到0opacity: 1; // 完全不透明}100% {transform: translate(-50%, -50%) scale(6); // 最終狀態:放大6倍opacity: 0; // 完全透明}}`;document.head.appendChild(style); // 將樣式添加到head中}// 創建3個雷達波紋div(依次延遲形成波紋效果)for (let i = 0; i < 3; i++) {const wave = document.createElement("div");wave.className = "radar_wave";// 設置波紋樣式wave.style.position = "absolute"; // 絕對定位wave.style.width = "20px"; // 寬度wave.style.height = "20px"; // 高度wave.style.border = "1px solid red"; // 紅色邊框wave.style.borderRadius = "50%"; // 圓形wave.style.boxShadow = "inset 0 0 5px 1px red"; // 內陰影效果wave.style.top = "50%"; // 垂直居中wave.style.left = "50%"; // 水平居中wave.style.transformOrigin = "center center"; // 變換中心點wave.style.transform = "translate(-50%, -50%) scale(0)"; // 初始縮小到0wave.style.animation = `radar_wave-animation 3s infinite`; // 應用動畫wave.style.animationDelay = `${i}s`; // 依次延遲(0s, 1s, 2s)container.appendChild(wave); // 將波紋添加到容器中}this.radarOverlayDom = container; // 緩存雷達DOMthis.viewer.container.appendChild(container); // 將雷達添加到Cesium容器中},
控制雷達動畫
// 控制雷達動畫顯示/隱藏狀態toggleRadarShowStatus() {// 如果雷達DOM不存在,則先創建if (!this.radarOverlayDom) {this.loadRadarLocationAnime();}// 切換顯示狀態this.radarVisible = !this.radarVisible;if (this.radarVisible) {// 計算雷達對應的Cesium笛卡爾坐標(緩存)this.radarPosition = Cesium.Cartesian3.fromDegrees(this.radarLonLat.lon,this.radarLonLat.lat);// 首次設置雷達位置const canvasPos = this.viewer.scene.cartesianToCanvasCoordinates(this.radarPosition);if (canvasPos) {// 計算DOM位置(居中顯示)this.radarOverlayDom.style.left = `${canvasPos.x - 100}px`; // 寬度的一半this.radarOverlayDom.style.top = `${canvasPos.y - 100}px`; // 高度的一半this.radarOverlayDom.style.display = "flex"; // 顯示雷達}// 注冊渲染循環監聽(每幀更新雷達位置)this.updateRadarPositionHandler = this.viewer.scene.preRender.addEventListener(() => {const updatedCanvasPos = this.viewer.scene.cartesianToCanvasCoordinates(this.radarPosition);if (updatedCanvasPos) {// 實時更新DOM位置,保持與Cesium場景同步this.radarOverlayDom.style.left = `${updatedCanvasPos.x - 100}px`;this.radarOverlayDom.style.top = `${updatedCanvasPos.y - 100}px`;}});} else {// 隱藏雷達并移除渲染循環監聽this.radarOverlayDom.style.display = "none";if (this.updateRadarPositionHandler) {this.updateRadarPositionHandler(); // 移除監聽this.updateRadarPositionHandler = null; // 清空引用}}},
這里的 loadRadarLocationAnime函數 用來創建雷達動畫,默認隱藏;toggleRadarShowStatus函數 用來控制雷達動畫,首次執行,顯示雷達動畫,再次執行,隱藏雷達動畫,循環往復。
4.3 模擬展示
事件組件
// 發送事件通知其他組件需要顯示雷達和車輛動畫
// 參數1: true 表示需要顯示動畫
// 參數2: this.realEventList 當前事件數據(如求助點位置等信息)
this.$bus.$emit('brotherEvent1', true, this.realEventList);// 發送事件通知其他組件需要隱藏雷達和車輛動畫
// 參數1: false 表示需要隱藏動畫
// 參數2: 未傳遞(此時參數2為undefined)
this.$bus.$emit('brotherEvent1', false);
地圖組件
// 事件推送和動畫顯示// 監聽名為 'brotherEvent1' 的事件(來自兄弟組件或其他模塊)this.$bus.$on('brotherEvent1', (res, data) => {// 如果事件返回 true,表示需要顯示雷達和車輛動畫if (res) {// 立即更新事件數據(不需要延遲)this.realEventList = data;// 延遲 1 秒后執行以下操作(確保 DOM 已更新)setTimeout(() => {// 加載雷達動畫(如果尚未加載)this.loadRadarLocationAnime();// 顯示雷達動畫this.toggleRadarShowStatus();// 加載車輛模型動畫(如果尚未加載)this.loadVehicleModelAnime();// 顯示車輛模型動畫this.toggleVehicleShowStatus();}, 1000); // 延遲 1 秒執行// 如果事件返回 false,表示需要隱藏雷達和車輛動畫} else if (res === false) {// 隱藏雷達動畫this.toggleRadarShowStatus();// 隱藏車輛模型動畫this.toggleVehicleShowStatus();}});
這里通過事件組件的 WebSocket 推流數據狀態和 EventBus 通信控制動畫顯示/隱藏:當收到?brotherEvent1(true, data)
?時,更新事件數據并延遲1秒加載雷達和車輛動畫;收到?brotherEvent1(false)
?時直接隱藏動畫;根據需求自行更改。
?
?
五、注意事項
注意事項與優化建議
5.1 資源加載與路徑問題
- 模型路徑:確保 GLB 文件路徑正確(如?
uri: "/static/glb/8jc.glb"
),避免跨域問題(可配置服務器 CORS 或使用相對路徑)。本文代碼里的 uri: "/glb/8jc.glb", 模型文件是放在public文件下的。
5.2 性能與內存管理
- 實體清理:使用?
viewer.entities.removeAll()
?銷毀不再需要的車輛實體,避免內存泄漏。 - 動畫頻率:雷達波紋?
waveInterval
?建議設為 500-1000ms,過短會導致 CPU 占用過高;車輛波紋?waveCount
?不建議超過 5 層。
5.3 兼容性與調試
- 瀏覽器支持:Cesium 依賴 WebGL 2.0,需確保用戶瀏覽器支持(可添加?
webgl-lint
?庫進行檢測)。 - 坐標調試:通過?
console.log(canvasPos)
?打印屏幕坐標,輔助定位雷達偏移問題;使用 Cesium 調試工具?viewer.scene.debugShowFramesPerSecond = true
?監控幀率變化。
?
?
六、本文總結
本文總結與擴展方向
擴展方向
本文通過 Cesium 實體系統與 HTML 動畫結合,實現了車輛與雷達的動態交互效果。實際項目中可進一步擴展:
- 數據驅動:接入 WebSocket 實時更新車輛位置與雷達事件數據。
- 視覺增強:為車輛模型添加燈光效果(
ModelStyle
),雷達波紋支持多顏色漸變。 - 交互升級:實現鼠標懸停時車輛信息彈窗、雷達波紋點擊縮放等高級功能。
延伸閱讀:
- Cesium 7 原文鏈接(含高速道路完整代碼)
- Cesium 官方模型加載文檔
- CSS3 動畫性能優化指南
通過兩篇文章的結合,可構建從 “基礎場景→動態交互→業務邏輯” 的完整 Cesium 可視化能力,適用于智慧交通、數字孿生等復雜場景開發。
本文圍繞 Cesium 中動態元素的核心需求,詳細講解了車輛模型與雷達動畫的完整實現流程,涵蓋坐標計算、實體渲染、交互控制及性能優化。結合前篇道路場景開發,可構建 “靜態場景 + 動態交互” 的完整可視化方案,適用于智慧交通、應急救援等領域。完整項目代碼可通過留言、私信作者獲取,歡迎一起交流探討 Cesium 開發技巧!
?
?
七、更多操作
請看,CesiumJS Develop?個人專欄
CesiumJShttps://blog.csdn.net/weixin_65793170/category_12356611.htmlhttps://blog.csdn.net/weixin_65793170/category_12356611.html
?
?
?
?
?