CesiumJS导出功能:截图、录像、KMZ三种结果一次拿齐
【免费下载链接】cesiumAn open-source JavaScript library for world-class 3D globes and maps :earth_americas:项目地址: https://gitcode.com/GitHub_Trending/ce/cesium
做汇报、留证、交接时,你常需要把 CesiumJS 场景变成可交付的文件:一张当前视角的截图、一段相机飞行录像,或一份能塞进 Google Earth 的地理数据。CesiumJS 的导出路径恰好覆盖这三类结果——画面导出走 Canvas 与 MediaRecorder,数据导出走内置的Cesium.exportKml,全部在浏览器端完成,无需服务端。
🧭 能力边界总览
先分清哪些是库原生提供的、哪些要你自己拼。画面类导出(截图/录像)依赖 WebGL Canvas 的标准能力,数据类导出依赖 Entity 集合,KML 序列化在 exportKml.js 里实现。注意:Cesium3DTileset、Primitive 这类图层对象不在exportKml的输入范围内。
| 能力 | 输入 | 输出 | 适用场景 |
|---|---|---|---|
| 截图 | 渲染完成的 canvas | PNG(DataURL 字符串或 Blob) | 汇报配图、问题留证 |
| 录像 | 场景持续渲染 + 相机动画 | WebM 视频文件 | 演示回放、方案汇报 |
| KML/KMZ 数据导出 | dataSource.entities集合 | .kml文本或.kmz压缩包 | 向 Google Earth、GIS 工具交接实体数据 |
| GeoJSON/CZML | 无原生导出函数,需自行序列化 | JSON 文本 | 矢量分析、时间动态数据存档 |
🏃 最短路径跑通
以截图为例,从 0 到拿到第一张图只要四步:
- 打开 CesiumJS 页面,构造 Viewer 时加一行
contextOptions: { webgl: { preserveDrawingBuffer: true } }——它告诉 WebGL 每帧渲染后保留画面缓冲,否则下一帧会清屏,你截到的就是空白。 - 调用
viewer.camera.flyTo把相机定位到目标视角,并监听viewer.camera.moveEnd,等视角稳定。 - 调用截图,拿到 PNG 的 DataURL:
viewer.scene.render(); const dataUrl = viewer.canvas.toDataURL("image/png");- 检查
dataUrl是否为非空data:image/png开头的字符串,然后用URL.createObjectURL或直接赋给<a download>落盘。
录像同理换掉第 3 步:用viewer.canvas.captureStream(30)拿到画面流,喂给MediaRecorder即可。数据导出则直接对已加载的 DataSource 调Cesium.exportKml,一个示例见下文场景拆解。
📦 按场景拆解用法
汇报材料里嵌入当前视角
解决什么问题:截图要在渲染完成时抓,抓到半透明加载帧或空白帧,汇报图就废了。具体做法:在camera.moveEnd回调里执行scene.render()再调canvas.toDataURL("image/png"),把"相机停稳"和"立即抓帧"绑在一起。关键参数:toDataURL的格式参数固定传"image/png",因为汇报图需要无损、支持透明底;若场景有半透明材质,PNG 比 JPEG 少一次色带失真。
相机飞行过程的演示录像
解决什么问题:静态图讲不清相机轨迹和时序,需要把flyTo过程录成视频。具体做法:调用canvas.captureStream(30)生成 MediaStream,再用new MediaRecorder(stream, { mimeType: "video/webm" })开始录制,在相机动画结束后调用recorder.stop()并在ondataavailable里收集 Blob。关键参数:帧率建议 30fps,再高体积近翻倍,肉眼差异很小;timeslice不传即可,默认按内部缓冲切块,避免小文件碎片。
实体数据交接给 Google Earth
解决什么问题:项目里用 Entity 描述的点位、路径、模型要交给第三方 GIS 工具,KML/KMZ 是兼容性最高的格式。具体做法:加载 DataSource 后调用官方示例同款流程,把模型等外部文件打进 KMZ(参考 export-kml 沙盒示例):
const { kmz } = await Cesium.exportKml({ entities: dataSource.entities, kmz: true, modelCallback: modelCallback, });关键参数:实体里含ModelGraphics时,modelCallback是必填的,回调要把 glTF 换成 COLLADA(.dae)路径并把.dae与贴图通过externalFiles挂进 KMZ,缺回调会直接抛 RuntimeError;kmz: true让库用 zip 把 KML 和外部文件打包,单文件交付最省事。
⚖️ 关键参数与取舍
| 参数 | 建议取值 | 理由 | 副作用 |
|---|---|---|---|
preserveDrawingBuffer | 需要截图/录像就传true | 关闭时帧渲染完即清屏,toDataURL只能拿到空白(默认false,见 Context.js 的选项说明) | 缓冲常驻显存,低端设备内存占用上升,长期开着可能轻微拖累帧率 |
captureStream帧率 | 30fps | 再高体积近翻倍,而飞行镜头的肉眼差异很小 | 帧率低于场景实际刷新率时,快速转场会有轻微跳帧 |
exportKml的kmz | 含外部资源时传true | KML 引用本地相对路径,对方机器路径对不上就丢图;KMZ 单包交付避免此问题 | 压缩打包有耗时,实体和纹理多时 Promise 等待变长 |
| 贴图引用方式 | 小图用 data URI,大图走Resource.fetchBlob外挂 | 库里对 data URI 会抓成 Blob 塞进 KMZ(texture_${n}.png),data URI 本身还比二进制大约 33% 体积 | 贴图原样进包,KMZ 体积随纹理尺寸线性增长 |
🕳️ 高频坑位与排查
- 现象:
toDataURL返回的图片是纯黑或纯透明。原因:preserveDrawingBuffer为默认false,抓帧时缓冲已清。处理:构造 Viewer 时开启该选项,并务必在camera.moveEnd之后调用scene.render()再截图。 - 现象:实体含 3D 模型时
exportKml报 RuntimeError。原因:库里遇到ModelGraphics但未收到modelCallback,直接抛错。处理:补上回调,返回 COLLADA 相对路径并把模型与贴图文件注册进externalFiles。 - 现象:KMZ 导出后体积远超预期,几 MB 变成上百 MB。原因:billboard 或 label 的贴图是 data URI,被整体打包进 KMZ。处理:大图改走
Resource.fetchBlob外挂引用,或先把贴图压缩到实际显示尺寸再导出。 - 现象:录像文件播放卡顿、丢帧严重。原因:主线程每帧还跑着后处理和复杂材质,编码帧跟不上渲染。处理:录制前降低场景复杂度(关
postProcessStages中的增强效果),或把渲染分辨率降半再录。
🧩 适用与不适用场景
适合:场景以 Entity 为主、交付目标是图片/视频/KML 类静态文件、且全程可跑在浏览器里的项目。不适合:需要导出Cesium3DTileset或 Primitive 图层——exportKml只接受 Entity 集合,3D Tiles 的交接要直接拷贝 tileset 资源;需要时间动态数据的完整存档——CesiumJS 没有原生 CZML 导出,得自己按 CZML 结构序列化 Entity 的时间属性,工作量明显大于 KML;需要服务端批量出图——浏览器方案受同源与内存限制,批量渲染应改用 headless 方案逐视角出图。取舍一句话:画面导出用 Canvas 标准 API 最稳,数据导出只有 KML 是库内一站式完成的,其余格式按目标系统选 GeoJSON 或 CZML 自行组装。
CesiumJS 的导出核心就三条线:Canvas 出图、MediaRecorder 出片、exportKml出数据。 按"先保缓冲、再等视角稳定、最后抓结果"的顺序操作,三类交付物都能一次拿齐。
【免费下载链接】cesiumAn open-source JavaScript library for world-class 3D globes and maps :earth_americas:项目地址: https://gitcode.com/GitHub_Trending/ce/cesium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考