开源!让二维变成三维立体雷达,提升项目的颜值

大家好,我是日拱一卒的攻城师不浪,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第42/100篇原创文章。

效果预览

www.bilibili.com/video/BV1L7...

前言

之前我们分享的都是平面雷达,总是感觉缺少一点立体感,或者说是科技感。

那今天我们就来聊聊如何在Cesium中实现一个立体的雷达扫描效果。

应用场景

立体雷达特效常见于以下应用场景:

  1. 军事指挥系统 :显示雷达站的探测覆盖范围,这个在军工项目中基本上是必不可少的功能了
  1. 通信网络规划:可视化信号基站的覆盖区域
  2. 智慧城市:展示特定设施的服务覆盖区域
  3. 气象预报:显示气象雷达的探测范围

原理分析

这个雷达扫描效果的实现主要涉及以下几个技术要点:

  1. 几何体构建 :使用Cesium实体系统 创建半圆球体立体墙体

  2. 动态更新 :通过Clock.onTick监听事件驱动扫描动画

  3. 坐标转换:在地理坐标和笛卡尔坐标间进行转换

  4. 数学计算:使用三角函数计算扫描扇区的点位

核心思路是通过不断更新墙体的位置来实现扫描动画,同时保持球体不变以表示覆盖范围。

代码详解

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);
}

这个方法是整个效果的核心,它通过以下步骤计算扇区的边缘点:

  1. 创建一个从地理坐标到笛卡尔坐标的转换矩阵

  2. 根据当前heading角度计算出半径方向上的偏移

  3. 将这个偏移应用到矩阵上,得到扇区边缘的一个点

  4. 将这个点转换回地理坐标

  5. 调用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(备注来意)。

相关推荐
青山Coding1 小时前
Cesium应用(三):全球气压可视化与气象时序图实现方案
前端·gis·cesium
孪创启航营1 天前
数字孪生二维热力图制作,看这篇文章就够了!
前端·three.js·cesium
不浪brown2 天前
用Cesium打造沉浸式雨天涟漪的真实感!
cesium
不浪brown4 天前
开源!3D带地形的区域地图,原来用Cesium几行代码就搞定了!(附源码)
cesium
青山Coding6 天前
Cesium应用(二):基于heatmap.js 的全球气象可视化实现方案
前端·gis·cesium
不浪brown8 天前
WebGIS必备技能!Cesium坡度坡向分析全解析
cesium
1H1R1M10 天前
同步绘制视锥几何体和实际相机视锥体
前端·javascript·cesium
青山Coding10 天前
Cesium应用(一):解决 Cesium 海量船舶轨迹点渲染难题:轨迹数据池方案实践
gis·cesium
锦岁10 天前
cesium-1.92源码编译
cesium