第五篇:给地球加点“魔法”——帧率、截图、底图控制,统统安排!
📘 专栏说明
本专栏旨在手把手带你从零开始,基于开源三维地球引擎 Cesium 封装一套功能完善、可复用的 WebGIS 增强型 SDK。内容涵盖核心封装思路、关键代码实现、常用 GIS 功能抽象,以及基于该 SDK 构建的 UI 组件库开发。如果你更关注结果而非实现过程,也可直接使用已发布的成果:
🌟 GitHub仓库 📦 NPM 包 ✨ 公众号:经纬码客(欢迎关注)
💡 建议:即便你打算直接使用 SDK,也推荐订阅本专栏 -- 理解设计思路,才能更灵活地扩展属于你自己的专属 GIS 能力!
由于作者需兼顾全职工作,更新主要安排在晚间或节假日,无法保证高频发布,但会持续迭代,直至 SDK 达到实际项目落地标准。届时将完整开源所有源码,供学习与商用(遵循许可证协议)。
大家好,我是 Cesium 酱(也可以叫我“本猿”),一名在 WebGIS 领域摸爬滚打多年的前端开发者。上一篇,我们一起封装了 Arc3DLab.Viewer,实现了“一行代码创建三维地球”。
但一个真正好用的 SDK,不能只停留在“能跑”,还要让开发者用得爽。
这一期,我们就来给 Viewer 类加几个超实用的小功能:
- ✅ 动态开关帧率显示(FPS)
- ✅ 一键开启/关闭地球光照与阴影
- ✅ 获取当前地图尺寸(width / height)
- ✅ 导出当前地图场景为 Base64 图片
- ✅ 灵活替换底图(ImageryLayer)
这些功能看似简单,但原生 Cesium 要么藏得深,要么写法啰嗦。
我们造轮子的目标:把复杂留给自己,把简洁留给用户。
准备好了吗?打开你的 Viewer.ts,我们继续敲代码!
🔧 第一步:添加帧率控制 —— fps 属性
很多Cesium开发者调试时需要看帧率,肯定每次都要写:
viewer.scene.debugShowFramesPerSecond = true
太麻烦!
我们在 Viewer 类中添加 getter/setter:
// src/core/Viewer.ts
/*** 控制帧率显示* @type {Boolean}*/
get fps() {return this.scene.debugShowFramesPerSecond
}
set fps(show: boolean) {this.scene.debugShowFramesPerSecond = show
}
✅ 使用方式:
viewer.fps = true // 开启帧率
console.log(viewer.fps) // 读取当前状态
是不是清爽多了?
💡 第二步:一键控制地球光影 —— lightShadow 属性
想让地球有明暗变化?需要同时开启两个设置:
globe.enableLightingshadows
我们把它合并成一个开关:
/*** 地球光源阴影* @type {Boolean}*/
set lightShadow(bool: boolean) {this.scene.globe.enableLighting = boolthis.shadows = bool
}
✅ 使用方式:
viewer.lightShadow = true // 开启真实光照 + 阴影
viewer.lightShadow = false // 关闭,性能更优
🌍 小知识:开启光照后,地形起伏会更真实,但对 GPU 要求更高。本猿一般是关闭的...没办法,小破本...
📏 第三步:获取地图尺寸 —— size 只读属性
有时候我们需要知道当前画布大小(比如做截图适配),原生要写:
const { width, height } = viewer.canvas
我们封装成一个只读属性,并提取为独立函数(便于复用):
先创建工具函数 src/utils/Scene.ts(后续场景相关的方法都将在此文件扩充):
// src/utils/Scene.ts
import { Viewer } from "../core/Viewer"
/*** 获取地图尺寸*/
export function mapSize(viewer: Viewer) {const { width, height } = viewer.canvasreturn { width, height }
}
然后在 Viewer.ts 中引用:
import { mapSize } from "../utils/Scene"
/*** 地图画布大小,例如:{width:1920,height:1080}* @type {Object}* @readonly*/
get size() {return mapSize(this)
}
✅ 使用方式:
console.log(viewer.size) // { width: 1920, height: 1080 }
📸 第四步:一键导出场景图片 —— image 只读属性
想把当前地球画面保存为图片?原生 toDataURL() 有时会导出黑屏(因为未渲染完成)。
我们加个保险,同样是在 src/utils/Scene.ts:
// src/utils/Scene.ts
import { Viewer } from "../core/Viewer"
/*** 获取地图图片(Base64)*/
export function mapImg(viewer: Viewer) {viewer.render() // 强制渲染一帧,避免黑屏return viewer.scene.canvas.toDataURL("image/png")
}
在 Viewer.ts 中添加:
import { mapImg } from "../utils/mapImg"
/*** 当前地图场景图片,base64格式* @type {String}* @readonly*/
get image() {return mapImg(this)
}
✅ 使用方式:
const base64 = viewer.image
const img = document.createElement('img')
img.src = base64
document.body.appendChild(img)
💡 提示:功能不大,但常用,用于生成报告、分享截图、自动化测试等场景。

🌐 第五步:灵活控制底图 —— baseImagery 属性
Cesium 的底图机制有点“隐晦”,没有明确的定义:
- 最底层的图层会被标记为
_isBaseLayer - 替换它需要先移除旧图层,再用
lowerToBottom()放到底部,反正挺烦人的设置
我们把它封装成一个属性:
/*** 场景底图* Cesium机制是最底层的图层为_isBaseLayer,通过lowerToBottom来控制* @type {Cesium.ImageryLayer}*/
get baseImagery() {//@ts-ignoreconst layers = this.imageryLayers._layersconst baseLayer = layers.find((layer: any) => layer._isBaseLayer)return baseLayer
}
set baseImagery(imagery: Cesium.ImageryLayer) {//@ts-ignoreconst baseLayer = this.imageryLayers._layers.find((layer: any) => layer._isBaseLayer)if (baseLayer) {this.imageryLayers.remove(baseLayer)}this.imageryLayers.lowerToBottom(imagery)
}
✅ 使用方式:
// 创建一个天地图影像图层
const tianditu = new Cesium.WebMapTileServiceImageryProvider({url: "http://t0.tianditu.gov.cn/img_w/wmts?tk=你的密钥",layer: "img",style: "default",format: "tiles",tileMatrixSetID: "w",maximumLevel: 18,
})
const imageryLayer = new Cesium.ImageryLayer(tianditu)
// 一键替换底图!
viewer.baseImagery = imageryLayer
⚠️ 注意:使用第三方地图服务请遵守其许可协议。
🧪 本地测试:试试这些新能力!
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>004-场景设置</title><script src="./Cesium/Cesium.js"></script><link rel="stylesheet" href="./Cesium/Widgets/widgets.css" /><script src="./lib/arc3dlab.umd.js"></script><script src="./assests/dat.gui.min.js"></script><style>html,body {margin: 0;padding: 0;width: 100%;height: 100%;}#cesiumContainer {width: 100%;height: 100%;position: relative;}#gui-box {position: absolute;left: 5px;top: 5px;z-index: 99;display: flex;}</style></head><body><div id="cesiumContainer"><div id="gui-box"></div></div><script>const viewer = new Arc3DLab.Viewer("cesiumContainer")initGui()function initGui() {const params = {message: "GUI面板-场景设置",fps: false,mapSize: "width:--,height:--",获取尺寸: function () {const { width, height } = viewer.sizeparams.mapSize = `width:${width},height:${height}`mapSizeController.updateDisplay()},场景截图: function () {const guiBox = document.getElementById("gui-box")const existingScreenshots = guiBox.querySelector("#screenshot")if (existingScreenshots) existingScreenshots.remove()const base64 = viewer.imageconst img = document.createElement("img")img.id = "screenshot"img.src = base64img.style.width = "300px"img.style.border = "1px solid #ccc"guiBox.appendChild(img)},}const gui = new dat.GUI({ autoPlace: false })const customContainer = document.getElementById("gui-box")customContainer.appendChild(gui.domElement)gui.add(params, "message")const boolFps = gui.add(params, "fps")boolFps.onFinishChange((val) => {viewer.fps = val})const mapSizeController = gui.add(params, "mapSize")gui.add(params, "获取尺寸")gui.add(params, "场景截图")}</script></body>
</html>
刷新页面,你会看到:
- 右上角显示 FPS
- 地球出现明暗变化
- 点击显示尺寸,点击插入截图!
🌟 项目开源,欢迎Star✨!
GitHub:https://github.com/jianlei-wang/Arc3DLab_SDK
NPM:https://www.npmjs.com/package/arc3dlab
Cesium 酱の百宝箱 · 第 5 篇
功能不在多,而在刚刚好。
2026 年伊始,与你共添一行魔法代码。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1173351.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!
本专栏旨在手把手带你从零开始,基于开源三维地球引擎 **Cesium** 封装一套功能完善、可复用的 **WebGIS 增强型 SDK**。内容涵盖核心封装思路、关键代码实现、常用 GIS 功能抽象,以及基于该 SDK 构建的 UI 组件库开发。