🚀 如何在内网中运行 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 文件上传接口,实现地图服务在线发布管理
相关推荐
高山我梦口香糖17 分钟前
[electron]预脚本不显示内联script
前端·javascript·electron
神探小白牙17 分钟前
vue-video-player视频保活成功确无法推送问题
前端·vue.js·音视频
Angel_girl3191 小时前
vue项目使用svg图标
前端·vue.js
難釋懷1 小时前
vue 项目中常用的 2 个 Ajax 库
前端·vue.js·ajax
Qian Xiaoo1 小时前
Ajax入门
前端·ajax·okhttp
爱生活的苏苏2 小时前
vue生成二维码图片+文字说明
前端·vue.js
拉不动的猪2 小时前
安卓和ios小程序开发中的兼容性问题举例
前端·javascript·面试
炫彩@之星2 小时前
Chrome书签的导出与导入:步骤图
前端·chrome
贩卖纯净水.2 小时前
浏览器兼容-polyfill-本地服务-优化
开发语言·前端·javascript
前端百草阁2 小时前
从npm库 Vue 组件到独立SDK:打包与 CDN 引入的最佳实践
前端·vue.js·npm