🚀 如何在内网中运行 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 文件上传接口,实现地图服务在线发布管理
相关推荐
zhangxingchao6 分钟前
Flutter入门:Flutter开发必备Dart基础
前端
佚名猫16 分钟前
vue3+vite+pnpm项目 使用monaco-editor常见问题
前端·vue3·vite·monacoeditor
满分观测网友z18 分钟前
vue的<router-link>的to里面的query和params的区别
前端·javascript·vue.js
BillKu20 分钟前
Vue3 + TypeSrcipt 防抖、防止重复点击实例
前端·javascript·vue.js
鱼樱前端21 分钟前
Vue3结合three和babylonjs实现3D数字展厅效果
前端·vue.js
Themberfue24 分钟前
Vue ⑥-路由
前端·javascript·vue.js
whatever who cares26 分钟前
React hook之useRef
前端·javascript·react.js
kooboo china.35 分钟前
Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(八):异步处理逻辑详解
前端·css·人工智能·编辑器·html·交互
天涯学馆38 分钟前
工厂模式在 JavaScript 中的深度应用
前端·javascript·面试
crary,记忆44 分钟前
Angular中Webpack与ngx-build-plus 浅学
前端·webpack·angular·angular.js