大家好,我是日拱一卒的
攻城师不浪
,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第42/100篇原创文章。
效果预览
www.bilibili.com/video/BV1L7...
前言
之前我们分享的都是平面雷达,总是感觉缺少一点立体感,或者说是科技感。
那今天我们就来聊聊如何在Cesium
中实现一个立体的雷达扫描效果。
应用场景
立体雷达特效常见于以下应用场景:
- 军事指挥系统 :显示雷达站的探测覆盖范围,这个在
军工项目
中基本上是必不可少的功能了

- 通信网络规划:可视化信号基站的覆盖区域
- 智慧城市:展示特定设施的服务覆盖区域
- 气象预报:显示气象雷达的探测范围

原理分析
这个雷达扫描效果的实现主要涉及以下几个技术要点:
-
几何体构建 :使用
Cesium
的实体系统 创建半圆球体
和立体墙体
-
动态更新 :通过
Clock.onTick
监听事件驱动扫描动画 -
坐标转换:在地理坐标和笛卡尔坐标间进行转换
-
数学计算:使用三角函数计算扫描扇区的点位
核心思路是通过不断更新墙体的位置来实现扫描动画,同时保持球体不变以表示覆盖范围。
代码详解
1. 球体和立体墙创建
javascript
addEntities() {
let entity = this.viewer.entities.add({
id: this.id,
position: this.position,
// 立体墙
wall: {
positions: new Cesium.CallbackProperty(() => {
return Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr);
}, false),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
// 球体
ellipsoid: {
radii: new Cesium.Cartesian3(
this.shortwaveRange,
this.shortwaveRange,
this.shortwaveRange
),
maximumCone: Cesium.Math.toRadians(90),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
outline: true,
outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
outlineWidth: 1,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
});
}
这个方法创建了两个关键几何体:
-
wall
:一个墙体,用于表示扫描的扇区,它的位置通过CallbackProperty
动态更新 -
ellipsoid
:一个球体,表示雷达的覆盖范围
几个关键参数:
-
shortwaveRange
:雷达的覆盖半径 -
position
:雷达所在的位置(经度、纬度)
两者都使用了半透明的青色材质#00dcff82
,增强了科技感。
2. 动画实现
javascript
addPostRender() {
this.tickListener = this.viewer.clock.onTick.addEventListener(() => {
this.heading += 1.0; //可调节转动速度
this.positionArr = this.calcPoints(
this.longitude,
this.latitude,
this.shortwaveRange,
this.heading
);
});
}
动画的核心在于监听Cesium
的时钟事件,每一帧更新heading
角度,并重新计算扇区的点位数组。
转动速度可以通过调整每帧增加的角度值来控制。
3. 扇区点位计算
javascript
calcPoints(x1, y1, radius, heading) {
var m = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(x1, y1)
);
var rx = radius * Math.cos((heading * Math.PI) / 180.0);
var ry = radius * Math.sin((heading * Math.PI) / 180.0);
var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
var d = Cesium.Matrix4.multiplyByPoint(
m,
translation,
new Cesium.Cartesian3()
);
var c = Cesium.Cartographic.fromCartesian(d);
var x2 = Cesium.Math.toDegrees(c.longitude);
var y2 = Cesium.Math.toDegrees(c.latitude);
return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}
这个方法是整个效果的核心,它通过以下步骤计算扇区的边缘点:
-
创建一个从地理坐标到笛卡尔坐标的转换矩阵
-
根据当前
heading
角度计算出半径方向上的偏移 -
将这个偏移应用到矩阵上,得到扇区边缘的一个点
-
将这个点转换回地理坐标
-
调用
computeCirclularFlight
方法计算扇区内的所有点
4. 扇区插值计算
javascript
computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
let positionArr = [];
positionArr.push(x1);
positionArr.push(y1);
positionArr.push(0);
var radius = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(x1, y1),
Cesium.Cartesian3.fromDegrees(x2, y2)
);
for (let i = fx; i <= fx + angle; i++) {
let h = radius * Math.sin((i * Math.PI) / 180.0);
let r = Math.cos((i * Math.PI) / 180.0);
let x = (x2 - x1) * r + x1;
let y = (y2 - y1) * r + y1;
positionArr.push(x);
positionArr.push(y);
positionArr.push(h);
}
return positionArr;
}
这个方法根据起点和终点计算出一个弧形路径上的所有点。
它首先将起点坐标添加到数组中,然后计算从起点到终点的距离作为半径,接着在指定角度范围内(这里是0到90度
)生成一系列点,并设置每个点的高度,形成一个立体的扇区。
5. 资源管理与控制方法
javascript
clear() {
// 停止时钟监听
if (this.tickListener) {
this.tickListener();
this.tickListener = null;
}
// 移除实体
if (this.viewer && this.id) {
const entity = this.viewer.entities.getById(this.id);
if (entity) {
this.viewer.entities.remove(entity);
}
}
// 清理属性
this.positionArr = [];
this.heading = 0;
}
类中还提供了多个实用的控制方法:
-
clear()
:清理资源但保留对象 -
destroy()
:完全销毁对象 -
stop()
:暂停动画 -
start()
:开始动画 -
hide()
:隐藏雷达效果 -
show()
:显示雷达效果
这些方法使得雷达效果更易于在不同场景中控制,提高了组件的可复用性。
使用示例
javascript
import RadarSolidScan from './RadarSolidScan.js';
// 创建雷达效果
const radar = new RadarSolidScan({
viewer: viewer,
id: 'radar1', // 唯一标识
position: [120, 36],
shortwaveRange: 50000 // 50公里的覆盖范围
});
最后
【完整源码地址】:github.com/tingyuxuan2...
想系统学习Cesium的小伙伴儿,可以了解下不浪的教程
《Cesium从入门到实战》
,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市
的完整项目,课程最近也更新了很多进阶内容,想了解课程大纲,+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群
可以加我:brown_7778(备注来意)。