WorldWideView:用 CesiumJS 搭一个实时地理情报平台
WorldWideView 是一个基于 CesiumJS 的开源实时地理空间可视化平台,技术栈为 Next.js + TypeScript,数据存储用 Supabase。它能同时接入飞机追踪、海事 AIS、交通摄像头、野火监控等多个异构数据源,在浏览器内渲染 10 万+ 个实时对象,帧率稳定在 60fps。
项目地址:https://github.com/silvertakana/worldwideview(200+ (opens in a new tab) Stars)
核心设计:数据源与渲染解耦
WorldWideView 的架构核心是插件化数据源 + 高性能批量渲染的分离设计。
渲染层只做一件事:高效地把数据画到 3D 地球上。它不关心数据来自哪里,格式是什么,更新频率是多少。这些都由各自的插件处理,插件将原始数据标准化为统一的地理坐标对象后交给渲染引擎。
这个设计的直接好处是:添加新数据源不需要改渲染逻辑,某个数据源出现延迟也不会阻塞其他数据源的渲染。

渲染性能:为什么能流畅处理 10 万+ 对象
CesiumJS 提供了两套渲染 API,选择哪套对性能影响巨大:
- Entity API:每个对象独立管理,适合对象少、交互丰富的场景(几十到几百个对象)
- Primitive API:将多个对象合并为一个批次提交 GPU,适合大规模静态场景
WorldWideView 选择了 Primitive API。1 万架飞机只需要一次 GPU Draw Call,而不是 1 万次。对象位置更新时直接修改 Primitive 内部的 buffer 数据,不重新创建对象。性能开销从 O(n) 降为接近 O(1)。
其他配套优化:
- 视锥剔除(Frustum Culling):只渲染当前相机视野内的对象,视野外直接跳过
- LOD:远处对象使用低面数模型,减少 GPU 顶点计算量
- 坐标预计算:经纬度到笛卡尔坐标的转换在 CPU 侧完成,只将最终坐标提交 GPU
数据源:每个插件对接了什么
项目内置 5 类数据源插件,每个插件背后都有明确的外部 API。
航空数据
主数据源为 OpenSky Network,通过 REST 轮询获取全球航班实时位置,刷新间隔 5 秒:
GET https://opensky-network.org/api/states/all认证走 OAuth2(client_credentials),免费账户每天 4000 积分,约支持 4 小时的连续拉取。项目在 .env 中支持配置多组凭据,按轮换顺序使用,单个账户额度耗尽后自动切换:
# .env.local
OPENSKY_CREDENTIALS=clientId1:clientSecret1,clientId2:clientSecret2军事航班走 adsb.fi,无需密钥,速率限制 1 req/s:
GET https://opendata.adsb.fi/api/v2/mil海事数据
对接 aisstream.io 的 WebSocket 流,订阅全球船舶位置报告(PositionReport),刷新间隔 60 秒:
WSS wss://stream.aisstream.io/v0/stream连接后发送订阅消息:
{
"APIKey": "<MARITIME_API_KEY>",
"BoundingBoxes": [[[-90, -180], [90, 180]]],
"FilterMessageTypes": ["PositionReport"]
}需要注册 aisstream.io 账户获取免费 API Key。支持货船、油轮、客船、军舰等 8 种船型分类。
交通摄像头
聚合三个官方交通数据源,全部公开免费无需密钥:
| 数据源 | API 地址 | 摄像头数量 | 覆盖地区 |
|---|---|---|---|
| GDOT | ArcGIS REST API | ~2,000 | 美国乔治亚州 |
| TfL JamCam | https://api.tfl.gov.uk/Place/Type/JamCam | ~900 | 英国伦敦 |
| Caltrans | https://cwwp2.dot.ca.gov/data/d{N}/cctv/ | ~3,400 | 美国加州(12个地区) |
摄像头数据本地缓存 TTL 为 24 小时。
野火监控
对接 NASA FIRMS(Fire Information and Management System),使用 VIIRS SNPP 卫星热点数据,每 5 分钟刷新:
GET https://firms.modaps.eosdis.nasa.gov/api/area/csv/{API_KEY}/VIIRS_SNPP_NRT/world/1API Key 可选,无 Key 时降级到公开 CSV 源。返回的热点数据按火点辐射功率(FRP)分为四级:
| 等级 | FRP 范围 | 显示颜色 |
|---|---|---|
| 低 | < 10 MW | 黄色 |
| 中 | 10–50 MW | 橙色 |
| 高 | 50–100 MW | 红色 |
| 极端 | > 100 MW | 深红 |
数据通过动态三层聚类(Macro ~220km / Meso ~55km / Micro ~5.5km)在不同缩放级别下合并显示,避免热点密集区域的图标重叠。
地理与边界数据
军事基地位置以 military_bases.geojson 内置在项目中,无需额外配置。其他地理边界支持标准 GeoJSON 格式。
底层基础设施
| 组件 | 技术 | 用途 |
|---|---|---|
| 3D 地球 | CesiumJS + Cesium Ion Token | 地形、影像、3D Tiles |
| 高清影像 | Bing Maps API(可选) | 替换默认影像 |
| 数据持久化 | Supabase(PostgreSQL) | 历史轨迹存储、用户认证 |
| 历史回放 | /api/aviation/history?time={ts} | 回放任意时间点的航班位置 |
本地运行
git clone https://github.com/silvertakana/worldwideview.git
cd worldwideview
npm install
cp .env.example .env.local # 填入 Cesium Ion Token 和 Supabase 配置
npm run dev访问 http://localhost:3000。只配置 Cesium Ion Token 即可启动,其余数据源按需开启。
如果需要添加自定义数据源,在 src/plugins/ 下新建一个目录,实现统一的插件接口(数据订阅、格式转换、对象类型定义),50–100 行代码即可完成一个基础插件。
总结
WorldWideView 是一个完整的实时地理可视化参考实现,不只是 Demo,而是有完整的数据接入、性能优化、历史存储方案。
它的适用场景是:多异构数据源、高更新频率、大规模对象数量的实时可视化需求。如果你的需求是静态地图或复杂地理分析,这个项目不是最佳选择。
架构上值得借鉴的两个核心思路:
- Primitive API 的批量渲染:把渲染代价从 O(n) 降到接近 O(1),是在 Web 端做大规模地理可视化的关键
- 插件化数据解耦:数据源与渲染层分离,使得不同频率、不同协议(REST / WebSocket)的数据源可以独立运行,互不干扰
GitHub 项目地址:https://github.com/silvertakana/worldwideview (opens in a new tab)