You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何围绕物体移动相机全角度观测?Cesium相机如何沿圆周路径环绕?

嘿,我来帮你搞定Cesium里相机围绕物体移动的两个需求,这俩都是项目里很常用的场景,我给你拆解清楚👇

一、手动操控相机围绕物体,从各个方位观测

要实现手动拖动鼠标就能绕着目标物体转,核心是让相机始终“盯着”目标,同时允许旋转、倾斜等操作:

  • 先定位到目标物体
    首先得获取目标物体的笛卡尔坐标(比如从entity的position或者primitive的位置取),然后让相机先飞到目标附近,或者直接设置初始视角:

    // 假设你有一个目标实体targetEntity
    const targetPosition = targetEntity.position.getValue(Cesium.JulianDate.now());
    // 先飞到目标附近,设置初始距离和视角
    viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height), // 或者基于targetPosition计算
        orientation: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(-30),
            roll: 0.0
        }
    });
    
  • 锁定相机看向目标
    使用camera.lookAt()方法让相机始终聚焦目标,这样后续拖动鼠标旋转时,就会围绕目标转:

    // 设置相机看向目标,同时保持一定距离
    const offset = new Cesium.Cartesian3(0.0, 5000.0, 2000.0); // x,y,z方向的偏移,控制相机和目标的距离/位置
    viewer.camera.lookAt(targetPosition, offset);
    
  • 配置相机控制器(可选)
    如果你想限制某些操作(比如禁止平移,只能旋转),可以调整屏幕空间相机控制器的参数:

    const controller = viewer.scene.screenSpaceCameraController;
    controller.enableTranslate = false; // 禁止平移
    controller.enableZoom = true; // 允许缩放
    controller.enableRotate = true; // 允许旋转(绕目标转的核心)
    controller.enableTilt = true; // 允许倾斜视角
    

    这样你拖动鼠标左键就可以绕目标旋转,右键倾斜,滚轮缩放,完美实现全方位观测。

二、让相机沿圆形路径自动围绕物体移动

自动沿圆形路径移动需要实时计算相机在圆周上的位置,然后更新相机视角,保持看向目标:

  • 定义基础参数
    先确定目标位置、圆形路径的半径、高度,以及旋转速度:

    const targetPosition = targetEntity.position.getValue(Cesium.JulianDate.now());
    const radius = 10000.0; // 圆形路径的半径,单位米
    const height = 3000.0; // 相机的飞行高度(相对于目标的高度)
    let angle = 0.0; // 当前旋转角度,初始为0
    const rotationSpeed = 0.005; // 旋转速度,数值越大转得越快
    
  • 实时更新相机位置
    使用requestAnimationFrame或者Cesium的Clock.onTick事件来实时计算相机位置并更新:

    function updateCameraPosition() {
        // 计算圆形路径上的相机位置:基于目标位置,绕Y轴(正北方向)旋转
        const cameraPosition = Cesium.Cartesian3.fromElements(
            targetPosition.x + radius * Math.cos(angle),
            targetPosition.y + radius * Math.sin(angle),
            targetPosition.z + height
        );
        // 设置相机位置,同时看向目标
        viewer.camera.setView({
            destination: cameraPosition,
            orientation: {
                heading: Cesium.Math.toRadians(180) + angle, // 让相机始终朝向目标,这里需要调整角度适配
                pitch: Cesium.Math.toRadians(-30), // 倾斜视角,看目标更自然
                roll: 0.0
            }
        });
        // 更新角度,实现持续旋转
        angle += rotationSpeed;
        // 循环调用,保持动画
        requestAnimationFrame(updateCameraPosition);
    }
    // 启动动画
    updateCameraPosition();
    
  • 优化细节

    • 如果想让相机的高度随角度变化(比如模拟航拍的起伏),可以把height改成height + 500 * Math.sin(angle*2)这类表达式。
    • 用Cesium的Clock事件替代requestAnimationFrame可以更好地和Cesium的时间系统同步:
      viewer.clock.onTick.addEventListener(function(clock) {
          angle += rotationSpeed * clock.multiplier; // 结合时钟倍率,控制速度
          // 同样的位置计算和相机设置逻辑
      });
      

这样就能实现平滑的自动绕圈效果啦~

内容的提问来源于stack exchange,提问作者meen

火山引擎 最新活动