今天来聊一下cesium的离线使用。某些情况下,我们的服务是部署在内网的,所以无法使用cesium官方提供的一些服务。
离线引入Cesium
Cesium-1.128下载 2025年4月发布的
为什么要下载呢?官网确实提供cdn引入:
html
<script src="https://cesium.com/downloads/cesiumjs/releases/1.128/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.128/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
哪有人就想直接把这个两个文件下载下来不就可以了嘛,下载下来然后本地引入,发现报错:
bash
Cesium.js:1 Uncaught SyntaxError: Invalid regular expression: /[×-ת؀-Û¿Ý-ݿࢠ-ࣿ]/: Range out of order in character class (at Cesium.js:1:1711082)
at new RegExp (<anonymous>)
其实Cesium.js中还引用很多js文件的。
正确引用: 将下载好压缩包解压:
我是直接在html文件测试的,所以只要关注Build文件夹,我猜测packages文件夹应该是npm包,使用框架的话应该关注这个文件夹。
点开Build文件夹:
Cesium文件夹是压缩后的代码,CesiumUnminifed文件夹是未压缩代码的。这个两个文件都是完整的cesium。 然后直接引入,跟官方cdn引入是一样的,只需要改变基础地址就行了,我的引入:
html
<script src="./assets/cesium-1.128/Build/CesiumUnminified/Cesium.js"></script>
<link
href="./assets/cesium-1.128/Build/CesiumUnminified/Widgets/widgets.css"
rel="stylesheet"
/>

到此为止,引入计算结束了。接下来就是代码层面的了,先看我的案列代码:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<script src="./assets/cesium-1.128/Build/CesiumUnminified/Cesium.js"></script>
<link
href="./assets/cesium-1.128/Build/CesiumUnminified/Widgets/widgets.css"
rel="stylesheet"
/>
</head>
<style>
* {
padding: 0;
margin: 0;
}
#cesiumContainer {
width: 100%;
height: 100vh;
}
</style>
<body>
<div id="cesiumContainer"></div>
<script type="module">
// 禁用Ion服务
Cesium.Ion.defaultAccessToken = undefined;
let viewer;
async function initCesium() {
viewer = new Cesium.Viewer('cesiumContainer', {
animation: false,
baseLayerPicker: false,
fullscreenButton: false,
vrButton: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
skyBox: false,
skyAtmosphere: false,
contextOptions: {
webgl: {
alpha: true,
failIfMajorPerformanceCaveat: false,
},
},
imageryProvider: false, //让控制台不报错 默认状态会加载cesium的底图
});
viewer.cesiumWidget.creditContainer.style.display = 'none';
// 添加底图
// const provider = await Cesium.SingleTileImageryProvider.fromUrl(
// 'http://127.0.0.1:8004/blue.jpg'
// );
// viewer.scene.imageryLayers.addImageryProvider(provider);
viewer.scene.imageryLayers.addImageryProvider(
new Cesium.TileMapServiceImageryProvider({
url: 'http://127.0.0.1:8004/map/{z}/{x}/{reverseY}.jpg',
fileExtension: 'jpg',
tilingScheme: new Cesium.GeographicTilingScheme(),
})
// new Cesium.UrlTemplateImageryProvider({
// url: 'http://192.168.5.228:8004/map/{z}/{x}/{reverseY}.jpg',
// fileExtension: 'jpg',
// tilingScheme: new Cesium.GeographicTilingScheme(),
// })
);
}
initCesium();
</script>
</body>
</html>
代码解读:
- Cesium.Ion.defaultAccessToken:既然是离线使用那么Cesium.Ion.defaultAccessToken就没有用了,我们设置undefined,设置undefined,是为了避免一些请求,而在内网环境下的话就会报错,为了避免报错设置undefined。
- 那些官方的组件就不要用了设置为false,具体的可以看Cesium.Viewer.ConstructorOptions
- baseLayerPicker设置false,也是避免不必要的报错。
- imageryProvider设置false,重点说一下这个配置项,其实这个配置项在新版本中已经移除了。如果ts的话大概率会报错,首先是还可以正常用,为什么移除了还要使用呢,主要原因就是如果不在配置项中设置的话,cesium就会默认加载cesium的地图服务,然后导致控制台报错


这里说一下其中有段注释的代码:
js
const provider = await Cesium.SingleTileImageryProvider.fromUrl(
'http://127.0.0.1:8004/blue.jpg'
);
viewer.scene.imageryLayers.addImageryProvider(provider);
为什么要说一下呢,就是这个SingleTileImageryProvider使用问ai和网上搜的都是错的 问ai回答我的是这样的:
js
function initCesium() {
viewer = new Cesium.Viewer('cesiumContainer', {
// ... existing code ...
imageryProvider: new Cesium.SingleTileImageryProvider({
url: './assets/img/blue.jpg',
rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0) // 添加地理范围
})
});
// ... existing code ...
}
使用ai的发现 页面一片空白。
新版的使用方式改成异步的了 await Cesium.SingleTileImageryProvider.fromUrl()加载图片。
部署地图影像服务
其实部署很简单,最麻烦的就是地图影像数据。这里感谢xingke提供的地图影像数据,
夸克网盘「地图影像」 链接:pan.quark.cn/s/5ac3d143e... 提取码:DrTh
两个压缩包一个是地图影像的,一个是地形的
下载好之后就可以选择服务类型,我这边使用nest.js部署一个本地测试的,很简单,去官网直接使用命令创建一个nest项目,然后在项目根目录创建一个public目录,然后将压缩包直接解压到public目录下,然后在项目根目录下的src/mian.ts中设置一下public的路径和跨域


ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';
import { NestExpressApplication } from '@nestjs/platform-express';
import { TransformInterceptor } from './core/interceptor/transform.interceptor';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// 配置 CORS
app.enableCors({
origin: true, // 允许所有来源访问,生产环境建议设置具体的域名
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});
app.useStaticAssets(join(__dirname, '..', 'public'));
app.useGlobalInterceptors(new TransformInterceptor());
await app.listen(8004, '127.0.0.1');
}
bootstrap();
替换成你的地址就可以了
这里说一下TileMapServiceImageryProvider中的tilingScheme:
GeographicTilingScheme (地理坐标切片方案):
diff
- 基于地理坐标系(经纬度)
- 适用于全球范围的数据展示
- 经度范围:-180° 到 180°
- 纬度范围:-90° 到 90°
- 在高纬度地区变形较小
WebMercatorTilingScheme (墨卡托投影切片方案):
diff
- 基于墨卡托投影
- 是最常用的网络地图切片方案
- 适用于 Google Maps、OpenStreetMap 等常见地图服务
- 在高纬度地区会产生较大变形
- 不能完全显示极地区域 这两种切片方案的主要区别:
Cesium-1.128版本目前是只有这两种tilingScheme