共计 2279 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在使用 Cesium 开发 3D 地形应用时,开发者经常遇到一个棘手问题:当相机位置移动时,原本应该固定在地表上的 Label 标注会跟随相机一起移动,导致标注位置错乱。这种现象在以下场景尤为明显:

- 倾斜查看地形时,标注会漂浮在空中
- 缩放视图时,标注与地表的相对位置发生变化
- 旋转场景时,标注可能完全脱离关联的地理位置
这种问题直接影响用户体验,使得地理信息展示失去准确性,特别是在需要精确定位标记的应用场景中(如智慧城市、应急救灾等)。
技术分析
问题的根源在于 Cesium 中坐标系统和高度参考的配置方式。Cesium 支持三种高度参考模式:
- NONE:忽略地形高度,使用绝对高度
- CLAMP_TO_GROUND:将对象固定在地形表面
- RELATIVE_TO_GROUND:相对于地形表面保持固定高度
当 Label 标注设置为 NONE 模式时,它会使用纯粹的笛卡尔坐标系,不与地形产生关联。而相机移动时会重新计算所有对象的世界坐标,导致标注位置看起来像是在跟随相机移动。
解决方案
1. 设置 heightReference
通过将 Label 的 heightReference 属性设置为 CLAMP_TO_GROUND 或 RELATIVE_TO_GROUND,可以让标注与地形建立关联:
viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(longitude, latitude),
label: {
text: '固定标注',
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// 其他样式配置...
}
});
2. 配置 verticalOrigin
verticalOrigin 决定了 Label 在垂直方向上的对齐方式,对于地形标注特别重要:
label: {
text: '优化对齐的标注',
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 从底部对齐
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
height: 5 // 距离地面 5 米
}
3. 地形数据适配
确保 terrainProvider 正确配置,这是 heightReference 工作的基础:
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'https://assets.agi.com/stk-terrain/world',
requestWaterMask: true,
requestVertexNormals: true
});
完整代码示例
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: new Cesium.CesiumTerrainProvider({url: 'https://assets.agi.com/stk-terrain/world'})
});
// 添加固定标注
viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(116.4, 39.9),
label: {
text: '北京',
font: '14pt sans-serif',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
height: 10, // 高于地面 10 米
pixelOffset: new Cesium.Cartesian2(0, -20) // 微调位置
}
});
// 相机初始位置
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000)
});
性能考量
- CLAMP_TO_GROUND 模式 :
- 优点:精确贴合地形
-
缺点:计算开销大,每个标注都需要实时计算地形高度
-
RELATIVE_TO_GROUND 模式 :
- 优点:性能较好
-
缺点:在地形起伏大的区域可能出现悬空或埋入地面
-
静态高度模式 :
- 优点:性能最佳
- 缺点:完全不考虑地形,仅适用于平坦区域
避坑指南
- 标注不显示 :
- 检查 terrainProvider 是否正确加载
-
确认 heightReference 不是 NONE
-
标注位置偏移 :
- 调整 verticalOrigin 和 pixelOffset
-
考虑地形采样精度,可能需要增加 height 值
-
性能问题 :
- 减少不必要的标注
- 使用 distanceDisplayCondition 控制显示范围
进阶建议
对于大量标注的场景,建议:
- 使用 PrimitiveCollection 而非 Entity API
- 实现 LOD(Level of Detail)机制
- 采用空间索引(如四叉树)管理标注
- 考虑 Web Worker 进行异步地形采样
通过以上优化,即使在复杂地形上展示数千个标注,也能保持流畅的交互体验。
总结
解决 Cesium 中 Label 标注随相机移动的问题,关键在于正确理解和使用 heightReference 系统。通过合理配置高度参考模式和垂直对齐方式,结合性能优化策略,可以构建既准确又高效的 3D 地理信息应用。本文提供的解决方案已在多个生产环境中验证,希望这些实践经验能帮助开发者少走弯路。
