一、低性能移动终端的Cesium痛点

现在不少做三维地图、数字孪生的项目,都会用到Cesium这个工具包,它能把地球、建筑、地形这些三维内容在网页上跑起来,功能很强。但问题来了,要是在性能差的手机上用,比如几年前的老安卓、内存小的苹果机型,打开后要么卡得动不了,要么手机发烫掉电快,甚至直接闪退。这不是Cesium本身的问题,是它默认的渲染策略是给电脑、好手机做的,没考虑差设备的情况。

先给大家说下常见的差设备情况:比如内存只有2GB的安卓机,CPU是几年前的中端型号,GPU性能弱,网络还是4G甚至更差的。这种设备跑Cesium,默认设置下,可能刚加载一个城市的三维模型,手机就开始发烫,10分钟掉电20%,操作地图的时候还一顿一顿的。

二、核心降级策略1:像素比压缩

2.1 什么是像素比压缩

首先得搞懂一个基础概念:像素比(devicePixelRatio),简单说就是屏幕上一个物理像素对应多少个逻辑像素。比如现在很多手机的像素比是2或者3,意思是屏幕上显示一个1px的内容,实际用2x2或者3x3个物理像素来渲染,这样显示更清晰。但对于差设备来说,渲染的像素越多,需要的计算量就越大,耗电也越快。

像素比压缩的思路很简单:给Cesium的渲染设置一个比设备实际像素比小的值,让它用更少的像素来渲染内容,这样计算量就降下来了。

2.2 具体实现示例

这里用JavaScript作为统一技术栈,给大家看完整的代码示例,包括注释。

// 技术栈:JavaScript(适用于Cesium 1.90+版本)
// 步骤1:先获取设备的实际像素比
const realPixelRatio = window.devicePixelRatio;

// 步骤2:定义一个压缩后的像素比,比如把实际像素比压缩到1(根据设备性能调整,也可以设为1.5等)
// 这里做个判断:如果设备像素比大于1.5,就压缩到1;否则用原像素比
const compressedPixelRatio = realPixelRatio > 1.5 ? 1 : realPixelRatio;

// 步骤3:初始化Cesium Viewer的时候,传入设置好的像素比
const viewer = new Cesium.Viewer('cesiumContainer', {
  // 核心设置:控制渲染的像素比
  resolutionScale: compressedPixelRatio,
  // 其他默认配置可以保留,这里只列和性能相关的
  terrain: Cesium.Terrain.fromWorldTerrain(), // 地形服务
  baseLayer: Cesium.ImageryLayer.fromWorldImagery() // 底图服务
});

// 补充:如果想动态调整(比如检测到设备性能太差的时候临时改),可以这样写
function updatePixelRatio(newRatio) {
  viewer.resolutionScale = newRatio;
}

2.3 优缺点和注意事项

优点很明显:实现简单,一行配置就能生效,对性能的提升非常直观,比如把像素比从2降到1,渲染的像素量直接砍半,计算量也会大幅下降。 缺点也有:压缩太狠的话,显示会变模糊,比如原本清晰的建筑边缘、文字会变虚,所以得把握好压缩的度。 注意事项:不能随便设成0.5以下,不然显示效果会差到没法用;另外可以加个设备性能检测的逻辑,比如先判断设备的内存、CPU核心数,再决定压缩比例,不是所有差设备都用一样的压缩值。

三、核心降级策略2:瓦片预取的功耗优化

3.1 什么是瓦片预取

Cesium的三维内容是分成一块一块的“瓦片”来加载的,比如你拖动地图,视角变了,它就会加载当前视角能看到的瓦片,没看到的就不加载。默认的预取策略是:只要视角附近的瓦片,哪怕暂时看不到,也提前加载好,这样拖动的时候不会卡。但这个策略有个问题:差设备的网络慢、处理能力弱,提前加载太多瓦片,会导致手机一直跑着加载、计算,耗电快,而且加载的内容可能根本用不上,浪费资源。

瓦片预取的功耗优化,就是调整预取的逻辑,让它只加载真正需要的瓦片,减少不必要的计算和网络请求。

3.2 具体实现示例

还是用JavaScript技术栈,给大家看完整的优化代码。

// 技术栈:JavaScript(适用于Cesium 1.90+版本)
// 首先初始化Viewer,和之前一样
const viewer = new Cesium.Viewer('cesiumContainer', {
  resolutionScale: 1, // 先开像素比压缩
  terrain: Cesium.Terrain.fromWorldTerrain(),
  baseLayer: Cesium.ImageryLayer.fromWorldImagery()
});

// 核心优化:调整瓦片预取的相关参数
// 1. 减少预取的瓦片层级:默认会预取更高层级(更清晰)的瓦片,这里限制只预取当前层级
viewer.scene.globe.maximumScreenSpaceError = 16; // 控制瓦片的精细度,值越大越粗糙,预取越少
// 解释:maximumScreenSpaceError是指瓦片在屏幕上的最大误差,值越大,瓦片可以越粗糙,加载的数量越少

// 2. 关闭非必要的预取:比如关闭地形数据的预取(如果不需要特别精细的地形的话)
viewer.scene.globe.terrainProvider = new Cesium.EllipsoidTerrainProvider(); // 用基础地形替代精细地形,减少预取

// 3. 动态调整预取逻辑:监听视角变化,只加载当前屏幕内的瓦片
viewer.scene.postRender.addEventListener(() => {
  // 获取当前视角能看到的瓦片范围
  const viewport = viewer.camera.computeViewRectangle();
  // 遍历所有已加载的瓦片,不在当前范围内的就卸载
  viewer.scene.globe.tileCache.forEach(tile => {
    if (!viewport.contains(tile.rectangle)) {
      tile.isVisible = false; // 标记为不可见,Cesium会自动卸载
    }
  });
});

// 补充:如果需要加载建筑模型(3D Tiles),也要调整预取参数
const tileset = new Cesium.Cesium3DTileset({
  url: 'https://example.com/tileset.json', // 替换成自己的3D Tiles地址
  // 核心参数:控制3D瓦片的预取
  maximumScreenSpaceError: 32, // 比地形的大,让模型更粗糙,预取更少
  skipLevelOfDetail: true, // 跳过细节层级,减少预取的瓦片数量
  baseScreenSpaceError: 1024 // 基础误差,值越大,预取越少
});
viewer.scene.primitives.add(tileset);

3.3 优缺点和注意事项

优点:能大幅减少不必要的网络请求和计算,比如原本预取10块瓦片,优化后只预取3块,手机的CPU、GPU不用一直处理没用的内容,耗电自然就降下来了。 缺点:如果预取太少,拖动地图的时候可能会出现“加载断层”,就是视角移动到新地方,内容还没加载出来,会有空白。 注意事项:调整maximumScreenSpaceError的时候,要慢慢试,比如先设成16,看效果,要是太模糊就调到8,要是太卡就调到32;另外动态卸载瓦片的逻辑要写对,别把当前需要的瓦片也卸载了。

四、两种策略的结合使用和适配场景

4.1 结合使用的效果

单独用像素比压缩或者瓦片预取,效果可能不够,最好是结合起来用。比如先通过设备检测,判断是差设备,然后把像素比压缩到1,同时把瓦片预取的参数调大,减少预取。这样既减少了渲染的计算量,又减少了加载和处理的内容,双重优化。

举个实际的测试例子:在一款内存2GB、CPU是骁龙625的安卓机上,默认设置打开城市三维地图,手机10分钟掉电22%,操作卡顿;结合两种策略后,10分钟掉电8%,操作流畅度提升了很多,显示效果也能接受。

4.2 适配场景

这两种策略适合的场景很明确:

  1. 面向大众用户的网页端三维应用,比如城市导览、景区展示,用户可能用各种性能的手机访问;
  2. 低带宽场景,比如用户在偏远地区用4G访问,优化预取可以减少网络请求,提升体验;
  3. 长时间使用的场景,比如工作人员用手机查看三维地图,可能连续用几十分钟,优化后不会因为发烫、掉电快影响使用。

不适合的场景也有:比如需要高精度展示的专业项目,比如建筑施工的三维模拟,这种对显示效果要求高,不能随便压缩像素比或者减少预取。

五、其他补充优化技巧

除了这两种核心策略,还有几个小技巧也能帮着优化: 第一个是关闭抗锯齿,抗锯齿是让边缘更平滑的功能,差设备开了会很卡,关闭的代码很简单:

// 技术栈:JavaScript
viewer.scene.postProcessStages.antiAliasing = false;

第二个是限制视角的移动范围,比如只让用户看某个城市的地图,不让用户把视角拉得太远,这样加载的瓦片数量会减少; 第三个是用低精度的模型,比如原本用的是面数很多的建筑模型,换成面数少的,渲染的时候计算量就小了。

六、文章总结

Cesium在差设备上的性能问题,核心是默认的渲染和预取策略没有适配低性能设备的能力,像素比压缩和瓦片预取的功耗优化是两个最有效、最容易实现的方向。像素比压缩是从渲染的计算量入手,通过减少渲染的像素数来降低负担;瓦片预取是从加载和处理的内容入手,通过减少不必要的预取来减少资源消耗。

在实际使用的时候,一定要结合设备的实际情况调整参数,不能照搬代码,要在不同的差设备上测试,找到性能和显示效果的平衡点。另外,这两种策略也可以和其他小优化结合起来,进一步提升差设备的体验。