第4章:CesiumJS 从入门到精通④:上帝之眼——Camera 基础操作与坐标系
本专栏正在连载中欢迎关注不迷路阅读时间约 25 分钟 | 硬核实操篇建议跟着代码一起敲写在前面前面三篇文章我们搭好了环境、理清了架构、拆完了 Viewer 参数。但你有没有发现一个尴尬的事 —— 我们还没正经学过怎么用代码精确控制相机飞到想去的地方。今天这篇文章就是来解决这个问题的。相机系统是 CesiumJS 中使用频率最高的子系统之一理解它你就能让地球按照你的剧本转起来。读完本文你会收获搞懂 CesiumJS 中的三种坐标体系Cartesian3、Cartographic、屏幕坐标掌握Cartesian3.fromDegrees()—— 你每天会用 50 次的函数彻底理解camera.flyTo()的每一个参数学会 heading /pitch/roll 控制相机朝向掌握zoomTo、lookAt、viewBoundingSphere、flyToBoundingSphere的区别一、先搞懂坐标系 —— 这是所有 位置 的基础1.1 为什么需要三种坐标系CesiumJS 内部有三种不同的坐标表示方式每一种都有自己的用武之地用户输入经纬度 → Cartesian3引擎计算 → 屏幕坐标用户点击 (116.4, 39.9) → (x, y, z) → (px, py)1.2 三种坐标速查坐标系Cesium 类型含义什么时候用地心笛卡尔Cartesian3以地球球心为原点的 (x, y, z) 坐标单位米大部分 API 的参数Entity.position、Camera.destination 等地理坐标Cartographic经度 / 纬度 / 高度单位弧度 / 弧度 / 米数学计算、插值、地形采样屏幕坐标Cartesian2浏览器窗口内的像素坐标 (x, y)鼠标事件处理1.3 坐标互转 —— 你每天都会用// ① 经纬度度→ Cartesian3最常用每天写50遍 const position Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 1000); // ② Cartesian3 → Cartographic地理坐标 const cartographic Cesium.Cartographic.fromCartesian(position); console.log(cartographic.longitude); // 弧度 console.log(cartographic.latitude); // 弧度 // ③ 弧度 ↔ 度 const degrees Cesium.Math.toDegrees(cartographic.longitude); const radians Cesium.Math.toRadians(116.4074); // ④ 3D坐标 → 屏幕坐标 const screenPoint Cesium.SceneTransforms.wgs84ToWindowCoordinates( viewer.scene, position );⚠️最容易犯的错Cartographic的经纬度单位是弧度不是度坐标偏移 90% 都是这里搞混了。1.4 一张图帮你记住用户界面 API 参数 内部存储 ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 116.4°E │ ──→ │ fromDeg │ ──→ │ Cartesian3│ │ 39.9°N │ │ rees() │ │ {x, y, z} │ │ 50000m │ └──────────┘ └──────────┘ └──────────┘ │ Cartographic .fromCartesian() │ ┌─────▼─────┐ │ Cartographic│ │ lon(弧度) │ │ lat(弧度) │ │ height(米) │ └─────────────┘二、Camera API 图谱六种飞行方式CesiumJS 提供了六种相机操作方法按使用频率排列方法一句话有动画吗setView()瞬间跳转到指定位置❌ 瞬移flyTo()飞行动画到指定位置✅ 平滑飞zoomTo()缩放视角以包含指定实体 / 数据源✅flyToBoundingSphere()飞到包围球✅lookAt()盯着某个目标点看但位置不变✅lookAtTransform()在局部参考系中看模型跟随✅三、flyTo () —— 使用频率 90% 的方法3.1 完整参数签名camera.flyTo({ destination : Cartesian3 | Rectangle, // 目标位置 orientation : { // 朝向 heading : 0, pitch : Cesium.Math.toRadians(-45), roll : 0, }, duration : 3, // 飞行秒数 easingFunction : Cesium.EasingFunction.QUADRATIC_IN_OUT, complete : () { console.log(到了); }, cancel : () { console.log(被取消了); }, });3.2 最常用的三种调用模式// 模式①飞到点最常用 viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 50000), orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-45), }, duration: 3, }); // 模式②飞到矩形区域俯瞰中国 viewer.camera.flyTo({ destination: Cesium.Rectangle.fromDegrees(73, 18, 135, 54), duration: 3, }); // 模式③飞到实体 viewer.flyTo(entity, { duration: 2, offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-30), 5000), });3.3 常用矩形范围// 定位中国全境 const china Cesium.Rectangle.fromDegrees(73, 18, 135, 54); // 定位北京市区 const beijing Cesium.Rectangle.fromDegrees(116.1, 39.7, 116.6, 40.1);四、理解 heading /pitch/roll想象你是一架飞机heading 水平方向左右转0 北90 东180 南270 西pitch 垂直方向上下看0 平视-90 俯视地面90 仰望天空roll 绕视线旋转// 上帝视角垂直向下看 heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-90), // 水平看地平线 heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(0),五、setView () —— 瞬间跳转setView和flyTo参数完全一样区别只有一个没有动画直接跳过去。// 瞬间跳转到北京上空 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 50000), orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-45), }, });适用场景页面初始化、重置视角、快速切换。六、其他定位方式6.1 zoomTo () —— 自动适配视野// 自动缩放以包含所有 Entity viewer.zoomTo(viewer.entities); // 自动缩放以包含某个数据源 viewer.zoomTo(dataSource);6.2 lookAt () —— 盯着目标看// 相机不动视线锁定目标 const target Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0); const offset new Cesium.HeadingPitchRange( Cesium.Math.toRadians(45), Cesium.Math.toRadians(-30), 10000 ); viewer.camera.lookAt(target, offset);七、缓动函数EasingFunction—— 飞行的节奏感类型效果推荐度QUADRATIC_IN_OUT慢→快→慢⭐⭐⭐⭐⭐ 默认CUBIC_IN慢起步⭐⭐⭐CUBIC_OUT慢停止⭐⭐⭐BOUNCE_OUT弹跳落地⭐⭐ 趣味viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 50000), easingFunction: Cesium.EasingFunction.BOUNCE_OUT, duration: 4, });八、实用技巧8.1 取消飞行viewer.camera.cancelFlight();8.2 飞回默认视角viewer.camera.flyHome(2);8.3 获取当前相机经纬度const pos viewer.camera.position; const carto Cesium.Cartographic.fromCartesian(pos); console.log(经度, Cesium.Math.toDegrees(carto.longitude)); console.log(纬度, Cesium.Math.toDegrees(carto.latitude));8.4 限制缩放距离const controller viewer.scene.screenSpaceCameraController; controller.minimumZoomDistance 1000; // 最近 1km controller.maximumZoomDistance 20000000; // 最远 20000km九、本篇总结这一篇我们搞懂了 CesiumJS 的相机系统基础。核心就三件事坐标转换Cartesian3.fromDegrees()是你最常用的一行代码飞行方式flyTo()统治 90% 的场景setView()瞬移、zoomTo()自动适配朝向控制heading 水平转、pitch 上下看、roll 歪头从下一篇开始我们进入 CesiumJS 最实用的部分 ——Entity 实体体系。你将学会用几行代码在地球上画出各种漂亮的标记、线条和形状。课后动手用flyTo让相机依次飞到北京、东京、纽约、伦敦形成 世界地标巡礼用不同的easingFunction飞到同一个位置感受动画差异用Rectangle.fromDegrees俯瞰中国全境实现一个按钮点击取消当前飞行获取并打印当前相机的经纬度 下一篇预告CesiumJS 从入门到精通⑤—— 万物皆实体Entity API 入门Point、Billboard、Label、颜色系统、增删改查…… 敬请期待