🚀 如何在内网中运行 Cesium?基于 NestJS 构建离线地形与影像服务

在构建内网三维 GIS 系统或工业级可视化平台时,很多开发者都会遇到 CesiumJS 依赖网络地图服务的问题,比如默认使用 Bing、Ion 提供的在线地形与影像服务。但在无网络、私有化部署或内网安全环境下,我们就必须提供离线的地图和地形服务。

本文将基于 NestJS + CesiumJS ,手把手实现一个离线地图瓦片服务 + 离线地形服务的完整方案。


🧰 技术选型

技术 用途
NestJS 后端服务框架,提供地图/地形文件
CesiumJS 前端三维可视化引擎
地图瓦片(TMS) 提供离线影像,如天地图、谷歌等
地形数据(QuantizedMesh) 提供离线地形数据支持
@nestjs/serve-static 提供静态文件服务

目录结构预览

bash 复制代码
cesium-offline-server/
├── src/
├── public/
│   ├── tiles/           # 离线影像瓦片(z/x/y.png)
│   └── terrain/         # 地形数据(layer.json + .terrain)
├── package.json
└── ...

一、准备地图和地形数据

1.1 离线地图瓦片(TMS)

你可以使用:

  • Global Mapper、QGIS 等工具裁剪下载地图
  • 参考天地图、谷歌影像瓦片命名规则(z/x/y.png)

最终结构:

arduino 复制代码
public/tiles/
├── 0/0/0.png
├── 1/0/0.png
├── 1/0/1.png
└── ...

1.2 离线地形数据(QuantizedMesh)

推荐使用以下工具生成:

地形目录结构如下:

arduino 复制代码
public/terrain/
├── layer.json
├── 0/0/0.terrain
├── 1/0/0.terrain
├── 1/0/1.terrain
└── ...

二、NestJS 项目搭建

2.1 创建 Nest 项目

bash 复制代码
nest new cesium-offline-server

2.2 安装静态资源模块

bash 复制代码
npm install @nestjs/serve-static

2.3 配置静态资源服务

编辑 app.module.ts

ts 复制代码
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';

@Module({
  imports: [
    // 映射 tiles 到 /tiles 路由
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'public/tiles'),
      serveRoot: '/tiles',
    }),
    // 映射 terrain 到 /terrain 路由
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'public/terrain'),
      serveRoot: '/terrain',
    }),
  ],
})
export class AppModule {}

2.4 开启跨域

修改 main.ts

ts 复制代码
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors(); // 必须开启
  await app.listen(3000);
}

三、前端 Cesium 接入离线地图和地形

3.1 离线地图瓦片加载

js 复制代码
const viewer = new Cesium.Viewer("cesiumContainer", {
  imageryProvider: new Cesium.UrlTemplateImageryProvider({
    url: "http://localhost:3000/tiles/{z}/{x}/{y}.png",
    tilingScheme: new Cesium.GeographicTilingScheme(), // WGS84
    maximumLevel: 18,
  }),
  baseLayerPicker: false,
  terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 暂不加载地形
});

3.2 离线地形加载

js 复制代码
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
  url: "http://localhost:3000/terrain",
  requestVertexNormals: true,
  requestWaterMask: true,
});

四、测试验证与排查建议

✅ 检查资源访问

确保能访问:

  • http://localhost:3000/tiles/0/0/0.png
  • http://localhost:3000/terrain/layer.json
  • http://localhost:3000/terrain/1/0/0.terrain

✅ layer.json 示例:

json 复制代码
{
  "tilejson": "2.1.0",
  "format": "quantized-mesh-1.0",
  "version": "1.0.0",
  "scheme": "tms",
  "tiles": ["{z}/{x}/{y}.terrain"],
  "attribution": "Offline Terrain",
  "bounds": [-180, -90, 180, 90],
  "minzoom": 0,
  "maxzoom": 14
}

✅ 浏览器调试工具 Network 查看请求是否 200


五、总结

通过本文我们完成了:

  • 使用 NestJS 快速部署离线地图和地形服务
  • 结构清晰地管理 tiles 和 terrain 资源
  • 在 Cesium 前端正确加载离线资源

✅ 优势

  • 📡 完全离线:适用于内网、矿井、无人区等环境
  • 🛡️ 私有数据保护:不暴露给外部 API
  • 性能更优:局域网传输,加载快无延迟

🔗 后续拓展

  • 支持多地图图层(如天地图、谷歌、OpenStreetMap 切换)
  • 加入图层控制 API,动态切换瓦片
  • 加入 NestJS 文件上传接口,实现地图服务在线发布管理
相关推荐
阿芯爱编程29 分钟前
最长和谐子序列,滑动窗口
前端·javascript·面试
你脸上有BUG1 小时前
Css实现悬浮对角线边框动效
前端·css·动画
烛阴1 小时前
开发者神器:如何在浏览器控制台玩转第三方库,让调试效率翻倍!
前端·javascript
crary,记忆1 小时前
Module Federation 和 Native Federation 的比较
前端·webpack·angular
why技术1 小时前
翻译翻译,什么叫“编程专用”的显示器?
前端·后端
拉不动的猪2 小时前
JQ常规面试题
前端·javascript·面试
海上彼尚2 小时前
Monorepo + PNPM 搭建高效多项目管理
前端·js·源代码管理
Random_index2 小时前
#Uniapp篇:chrome调试&&unapp适配
前端·chrome·uni-app
Shimeng_19893 小时前
前端如何通过(手机)扫描二维码下载app
前端·javascript·vue.js·二维码·扫描二维码下载软件app