不用专业GIS软件,这个开源项目让你用Web做实时地理数据平台

如果你需要做飞机追踪、船舶监控或卫星轨道预测,通常的做法是用 ArcGIS 或其他专业 GIS 软件。但最近看到一个开源项目,有人用 Web 技术做出了一个实时地理空间情报平台,名叫 WorldWideView

这个项目基于 CesiumJS(一个 Web 3D 地球库),但关键的不是"又是一个地球",而是它的核心设计思想——模块化的数据源 + 高性能的实时渲染。它能同时追踪飞机、船舶、卫星这些完全不同的数据源,在一个 3D 地球上流畅地呈现,而且支持实时更新。

200+ 个 GitHub Star,说明很多人觉得这个思路很有价值。

为什么值得关注

1. 10万+对象也能实时渲染

在 Web 上用 3D 呈现地理数据,性能一直是个瓶颈。GIS 数据往往是海量的——几千条航线、几万个基站、几十万个地形点。怎么在浏览器里流畅地显示?

WorldWideView 用了一个关键优化:Cesium Primitives。与其把每个飞机、每艘船都当成一个独立的 3D 对象(这样 GPU 压力很大),不如把它们合并成一个"原始几何体",然后用数据驱动批量渲染。这样做的结果是,即使有 10 万+ 个对象同时显示,帧率仍然很稳定。

这个思想和"大场景优化"是一个道理,但在地理可视化领域的应用并不多见。

2. 开放的插件系统,不用改核心代码

WorldWideView 的设计把核心和数据源分离了。核心只负责"如何高效地渲染这些数据",而具体"什么数据"则通过插件来扩展。

这意味着什么?

  • 想接入飞机数据?写个飞机插件,处理 ADS-B 数据流
  • 想接入海事数据?写个 AIS 插件,处理船舶位置信息
  • 想接入卫星轨道?写个轨道插件,计算实时位置

每个数据源都是独立的模块,互不影响。这样做的好处是,你可以轻松地混搭任意组合——同时显示飞机、船舶、卫星,或者只显示其中某些,完全由你决定。而且新增一个数据源时,不需要改一行核心代码。

3. 实时更新和平滑动画

地理数据平台最重要的就是"实时"。飞机不能显示旧位置,卫星轨道要每秒更新。

WorldWideView 内置了实时数据流处理和平滑动画。系统会自动在数据点之间插值计算,让移动看起来流畅,而不是"一跳一跳"。这是看起来专业和业余的重要差别。

同时,系统支持"Oriented Icons"——飞机、船舶等图标会自动转向,指向它们的运动方向。这些细节让整个可视化看起来很专业。

核心架构:为什么这样设计

如果你看代码,会发现这个项目的设计非常清晰:

1. 数据源无关的核心

WorldWideView 的核心不关心你的数据是什么。它只知道:"给我一个数据流,我来帮你渲染成 3D 地球上的元素"。这意味着核心逻辑非常稳定,不会因为新增一个数据源而变得复杂。

2. 插件即数据源

每个数据源(飞机、船舶、卫星)实现相同的接口:

  • 订阅数据流 → 源源不断地获取位置数据
  • 转换数据格式 → 统一成系统理解的格式
  • 渲染到地球 → 由核心引擎负责高效渲染

这种设计让系统非常灵活。你可以用一个插件来管理 100 架飞机,也可以用同一个插件同时管理飞机、无人机、直升机——只要它们的数据格式兼容。

3. 分离渲染和数据处理

高性能的秘诀在于不让数据处理成为瓶颈。WorldWideView 用 TypeScript + Next.js 来做数据处理和业务逻辑,然后把"怎么渲染"这个任务交给 CesiumJS。数据处理可以在后端做,也可以在浏览器做,CesiumJS 只负责把这些数据高效地显示出来。

核心技术实现

如果你想深入理解为什么这个项目能在浏览器里流畅地处理 10 万+ 对象,这一节讲几个关键的技术决策:

1. Cesium Primitives:批量渲染的核心

CesiumJS 有两种方式来渲染地球上的对象:

  • Entity API - 每个飞机、船舶是一个独立的 Entity 对象,功能丰富但性能一般
  • Primitive API - 把多个对象打包成一个 Primitive,由 GPU 批量渲染

WorldWideView 选择了 Primitive API,理由很简单:Entity API 适合显示几十个对象,Primitive API 适合几万甚至几十万个。

具体怎么做的?假设你有 1 万架飞机要显示:

  1. 不是创建 1 万个 Entity 对象(这会让浏览器卡死)
  2. 而是创建一个大的 Primitive,内部包含 1 万个"飞机"
  3. 这个 Primitive 只需要一次 GPU 绘制调用,而不是 1 万次
  4. 当飞机位置更新时,只需要更新 Primitive 内部的数据,不需要重新创建对象

这样做的效果是,性能开销从"随对象数量线性增长"变成"基本固定"。

2. 实时数据流处理:WebSocket + 数据变换管道

飞机、船舶、卫星的数据不是一次性加载的,而是源源不断的流数据。WorldWideView 的做法是:

  • 用 WebSocket 或 HTTP 长连接接收实时数据
  • 数据到达后立即进入一个"转换管道"
  • 每个插件定义自己的转换逻辑(如何把原始数据转成坐标 + 属性)
  • 转换后的数据交给渲染引擎

这个设计的妙处在于,数据处理和渲染完全解耦。数据可以在浏览器处理,也可以在服务器端预处理,甚至可以在 WebWorker 中处理(避免阻塞主线程)。

3. 插件系统的接口约定

WorldWideView 的插件必须实现一个统一的接口。简化来说大概是这样:

interface DataSource {
  // 订阅数据流
  subscribe(callback: (data) => void): void;
 
  // 把原始数据转成{经度, 纬度, 高度, 方向, 属性}
  transform(rawData: any): GeoPosition;
 
  // 告诉渲染引擎这是什么类型的对象(飞机/船舶/卫星)
  getObjectType(): string;
}

只要插件实现了这个接口,核心引擎就知道怎么处理它。这是一个非常聪明的设计——核心不需要知道飞机数据长什么样,不需要知道卫星轨道怎么计算,它只需要"拿到数据 → 渲染"。

4. 地理坐标系统和性能优化

地理数据涉及两个坐标系统的转换:

  • 经纬度坐标 - 地球表面位置(如 GPS 坐标)
  • 笛卡尔坐标 - 3D 图形学坐标(屏幕渲染需要)

这个转换在 WebGL 中是很贵的操作。WorldWideView 的做法是:

  • 大部分计算在 CPU 端完成(JavaScript)
  • 只把最终的 3D 坐标送到 GPU
  • 或者把转换逻辑写在 GPU Shader 中,由 GPU 并行计算

这样能显著降低 CPU 压力,腾出性能给数据处理。

5. 内存管理和动态加载

10 万个对象的数据量是很大的。WorldWideView 用了几个策略来管理内存:

  • 视锥剔除 - 只加载相机能看到的地理区域的数据
  • LOD(细节级别) - 远处的飞机用简单的图标,近处用复杂的模型
  • 数据流预缓冲 - 新数据到达时不是立即全部加载,而是按需缓冲,旧数据逐步释放

这些优化保证了即使数据源源不断涌入,内存占用也能保持在合理范围内。

适合哪些场景

适合的场景:

  • 航空公司的航班实时监控系统
  • 海事部门的船舶追踪平台
  • 卫星地面站的轨道监控
  • 物流企业的车队管理
  • 无人机集群控制系统
  • 紧急救援的实时指挥中心

这些场景的共同点是:数据源多样(不只是一种数据),更新频繁(实时性要求高),对象数量大(性能要求高)。

不太适合的场景:

  • 静态地图应用(不需要实时更新)
  • 复杂的地理分析(需要更多的 GIS 工具)
  • 超大规模数据集(100+ 万个对象可能需要额外优化)

数据源从哪里来

WorldWideView 的核心价值就在于它能把多个不同的数据源整合到一个地球上。根据项目的代码,它内置了 7 种数据源插件,每种插件连接到不同的数据提供方。

项目内置的 7 种数据源

数据源类型使用的 API/服务覆盖范围成本
航空数据OpenSky Network / adsb.fi全球飞行中的商业航班免费(adsb.fi)/ 免费+付费(OpenSky)
海事数据内置 AIS 接收器支持全球海域船舶实时位置取决于 AIS 数据源
摄像头监控Insecam API全球开放网络摄像头免费
地理数据GeoJSON 标准格式自定义地理边界和特征免费
地缘政治边界内置数据库国家、省份、地区边界免费
军事设施military_bases.geojson全球军事基地位置公开数据
野火监控实时野火追踪数据源全球野火分布免费/付费

关键数据源详解

1. 航空数据 - OpenSky Network + adsb.fi

项目优先使用这两个数据源:

  • OpenSky Networkhttps://opensky-network.org)- (opens in a new tab) 全球最大的开放 ADS-B 数据库

    • 免费层:支持基础 API 访问
    • 付费层:无限制 API 额度
    • 特色:项目配置支持"多账户轮换"(comma-separated clientId:clientSecret pairs),可以绕过单账户 4000 积分/天的限制
  • adsb.fihttps://adsb.fi)- (opens in a new tab) 军用和民用航空数据

    • 完全开放,不需要 API 密钥
    • 速率限制:1 请求/秒
    • 更新频率:实时

2. 摄像头数据 - Insecam

项目集成了 insecam-api,可以获取全球开放的网络摄像头实时画面。这是一个独特的功能——很多地方的网络摄像头因为没有正确配置安全认证,导致直播流公开可访问。

3. 地形和影像 - Cesium Ion + Bing Maps

用于渲染高保真的地球背景:

  • Cesium Ion Token - 提供官方 3D 地形和默认影像
  • Bing Maps API(可选)- 提供更高分辨率的卫星影像

4. 数据存储 - Supabase

所有实时数据都可以持久化到 Supabase(基于 PostgreSQL 的 BaaS 平台):

  • 保存历史追踪轨迹
  • 支持用户账户和认证
  • 支持实时数据库订阅

怎么创建自定义数据源插件

如果想添加自己的数据源,项目的架构非常开放。在 src/plugins/ 目录中,每个插件遵循统一的接口。大致步骤是:

  1. src/plugins/ 下创建新文件夹,比如 src/plugins/mydata/

  2. 实现标准接口(TypeScript):

// plugin interface
export interface DataSourcePlugin {
  name: string;           // 数据源名称
  description: string;    // 描述
  subscribe(callback: (data) => void): void;  // 订阅数据流
  transform(rawData: any): GeoPosition;       // 转换为地理坐标
  getObjectType(): string;                    // 对象类型
}
  1. 数据格式转换 - 把原始数据转成:
{
  latitude: number,
  longitude: number,
  altitude?: number,
  heading?: number,  // 方向角度
  properties?: object  // 其他属性
}
  1. 配置环境变量.env.local)- 如果数据源需要 API 密钥或端点

  2. 在主应用中注册插件 - 告诉系统这个新插件存在

得益于模块化设计,添加一个新数据源只需要 50-100 行代码。项目文档提供了完整的示例。

项目还支持的高级特性

  • WebSocket 实时推流 - 用 ws 库接收实时数据流
  • HLS 视频流 - 用 hls.js 在地图上播放实时视频
  • 多账户 API 轮换 - 绕过 API 速率限制,支持水平扩展

怎么体验

如果你想看看效果,拉下代码很简单:

git clone https://github.com/silvertakana/worldwideview.git
cd worldwideview
npm install
npm run dev

打开 http://localhost:3000,你就能看到一个 3D 地球。项目预置了一些演示数据源(飞机、卫星等),直接就能看到各种数据在地球上实时运动的效果。

如果你想深入研究代码或自己添加数据源,项目提供了完整的文档:

  • 架构设计文档 - 理解为什么这样设计
  • 插件开发指南 - 如何写一个自定义数据源
  • API 文档 - 核心系统的接口说明

写在最后

WorldWideView 这个项目的价值,不只是"又一个地理可视化工具",而是展示了如何用 Web 技术架构一个专业级别的实时数据平台

很多人以为做飞机监控、船舶追踪这种系统必须用专业 GIS 软件或者特殊的行业方案。但这个项目证明了,用开源的 Web 技术,只要设计得当,也能达到专业级的效果——而且代码完全透明,可以自由定制。

如果你的项目涉及实时地理数据展示、多源数据融合、或者需要在 Web 上做地理信息系统,这个项目的设计思想值得深入学习。特别是它的"模块化数据源"和"高性能渲染"这两个核心思想,可以应用到很多其他场景。


GitHub 项目地址:https://github.com/silvertakana/worldwideview (opens in a new tab)