Cesium 二三维视图联动
近期做了二三维视图联动,简单记录一下。
主要功能就是同时开启二维和三维视图一起查看。
大概思路就是新创建一个 2D 视图,相机实时同步(其实部分资源也应该同步,不过这需要做一个数据状态管理的功能,让数据在两个视图同步,懒得做了,后面要做资源管理的功能再说吧)。
二维和三维视图其实相机焦点是有区别的,因为二维视图只有平移和缩放,没有旋转,故如何正确找到三维视图中的相机焦点是关键。
方法一:获取屏幕中心坐标,转为世界坐标
// canvas 中心位置为相机焦点 let viewCenter = new Cesium.Cartesian2( Math.floor(this.#viewer3D.canvas.clientWidth / 2), Math.floor(this.#viewer3D.canvas.clientHeight / 2) ); // 给定中心的像素,获取世界位置 let worldPosition = this.#viewer3D.scene.camera.pickEllipsoid( viewCenter, this.#viewer3D.scene.globe.ellipsoid );
方法二:通过射线求交获取坐标
构建射线:
// 构建相机射线 let ray = new Cesium.Ray( this.#viewer3D.camera.positionWC, this.#viewer3D.camera.directionWC );
求射线与椭球交点:
方法1:
使用IntersectionTests,获取射线与椭球交点,注意,Intercal 属性包括两个标量,因为交点应该是两个,正面与反面,我们取正面的交点,然后通过 getPoint 方法获取具体坐标
let interval = Cesium.IntersectionTests.rayEllipsoid( ray, this.#viewer3D.scene.globe.ellipsoid ); let worldPosition = Cesium.Ray.getPoint(ray, interval.start);
方法2:
使用 global 中的 pick 方法直接获取
let worldPosition = this.#viewer3D.scene.globe.pick( ray, this.#viewer3D.scene )
其实方法还有很多,不一一列举了
获取到坐标后,我们需要获取缩放距离
Cartesian3 提供了计算方法,我们只需要计算出高度,设置 camera 即可
// 同步相机视角 if (Cesium.defined(worldPosition)) { // 计算高度 let distance = Cesium.Cartesian3.distance( worldPosition!, this.#viewer3D.camera.positionWC ); this.#viewer2D!.camera.lookAt( worldPosition!, new Cesium.Cartesian3(0, 0, distance) ); }
若想只保存 3D 视图的移动,让 2D 视图跟随,也可关闭 2D 视图的鼠标控制
// 禁止移动缩放 this.#viewer2D.scene.screenSpaceCameraController.enableZoom = false; this.#viewer2D.scene.screenSpaceCameraController.enableTranslate = false;
若想更换其他厂商的地图,直接在新建 viewer 时设置即可
完整版请移步LiZzhi/cesium-plugin (github.com),如果对您有帮助,请给我一颗star,谢谢。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~