Skip to content

在二维GIS中移动视域或者进行空间漫游,只需设置视域范围中心点的经纬度坐标和图层等级,可以理解为只需确定视点位置即可,不存在视线方向问题。而三维中,不仅要确定视点位置,还要确定视线方向,一旦视线方向与目标物相反,那么在视域里面看不到目标物。

Cesium是通过相机控制场景中的视域,旋转、缩放、平移等操作都可控制相机移动。当用户拖动地球移动,其实移动的是相机,而不是地球,这种相对运动就产生了场景移动的效果。

相机的方向和位置

Cesium的视角移动不仅需要设定相机的位置,还需要相机方向。Cesium中的orientation函数用于设定方向,不仅是相机方向,还包括模型的方向等。

Cesium的Orientation是一个对象,一般包含heading、pitch和roll三个参数,这三个参数非必选,不设置则采用默认值。我们先来看看右手笛卡尔坐标系。

![image-20240221204830378](/Users/dllcnx/Library/Application Support/typora-user-images/image-20240221204830378.png)

  • pitch:围绕X轴旋转,也叫俯仰角,因为绕X轴旋转,可以控制飞机俯仰角,往上还是往下。
  • yaw:围绕Y旋转,也叫偏航角,因为绕Y轴旋转,可以控制飞机飞行方向,往左还是往右。
  • roll:围绕Z轴旋转,也叫翻滚角,因为绕Z轴旋转,可以控制飞机做翻滚旋转

Cesium中相机Orientation设定原理和右手笛卡尔坐标系原理相同,只是yaw用heading表示,两个含义其实都是水平旋转。Cesium中X轴方向为正北。

  • heading:默认正北,正角度为向东旋转,即水平旋转,也叫偏航角。
  • pitch:默认角度为-90,即朝向地面,正角度为平面之上,负角度为平面之下,即上下旋转,也叫俯仰角。
  • roll:默认旋转角度为0,左右旋转,正角度向右,负角度向左,也叫翻滚角。

上边就是Orientation的含义,而destination是指相机位置的三维坐标(可以用经纬度和大地高表达)。

示例:

javascript
viewer.camera.setView({
	destination: Cesium.Cartesian3.fromDegrees(lon,lat,height);
	orientation: {
			heading: Cesium.Math.toRadians(0.0), //默认值
			pitch: Cesium.Math.toRadians(-90.0), // 默认值
			roll: 0.0 //默认值
	}
})

相机系统分类与用法

针对不同的场景与需求,Cesium有多种操作相机的方法。常见的有setViewflyToviewBoundingSpherelooAt等等。

setView(options)

通过设定目标点三维坐标(经纬度,高度)以及视线方向,快速的将视角调整到定义的可视区域。没有中间动画过程。

js
// 1. 自上向下视角
viewer.camera.setView({
    destination : Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0)
});

// 2. 设置视角俯仰角,翻滚角,偏航角
viewer.camera.setView({
    destination : cartesianPosition,
    orientation: {
        heading : Cesium.Math.toRadians(90.0), // east, default value is 0.0 (north)
        pitch : Cesium.Math.toRadians(-90),    // default value (looking down)
        roll : 0.0                             // default value
    }
});

// 3. 保持相机位置不变的情况下改变摄像机的方位、俯仰和翻滚
viewer.camera.setView({
    orientation: {
        heading : Cesium.Math.toRadians(90.0), // east, default value is 0.0 (north)
        pitch : Cesium.Math.toRadians(-90),    // default value (looking down)
        roll : 0.0                             // default value
    }
});


// 4. 俯视视图中的视图矩形
viewer.camera.setView({
    destination : Cesium.Rectangle.fromDegrees(west, south, east, north)
});

// 5. 使用单位向量设置位置和方向
viewer.camera.setView({
    destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0),
    orientation : {
        direction : new Cesium.Cartesian3(-0.04231243104240401, -0.20123236049443421, -0.97862924300734),
        up : new Cesium.Cartesian3(-0.47934589305293746, -0.8553216253114552, 0.1966022179118339)
    }
});

flyTo(options)

不同于setView快速视角,flyTo则是将摄像机从当前位置移动到新位置,并且具有逐步切换的动画效果,可设置飞行时间。相机会根据当前视点位置自动设定飞行速度和飞行路线,视线巡游式视域切换。

js
// 1. Fly to a position with a top-down view
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0)
});

// 2. Fly to a Rectangle with a top-down view
viewer.camera.flyTo({
    destination : Cesium.Rectangle.fromDegrees(west, south, east, north)
});

// 3. Fly to a position with an orientation using unit vectors.
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0),
    orientation : {
        direction : new Cesium.Cartesian3(-0.04231243104240401, -0.20123236049443421, -0.97862924300734),
        up : new Cesium.Cartesian3(-0.47934589305293746, -0.8553216253114552, 0.1966022179118339)
    }
});

// 4. Fly to a position with an orientation using heading, pitch and roll.
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0),
    orientation : {
        heading : Cesium.Math.toRadians(175.0),
        pitch : Cesium.Math.toRadians(-35.0),
        roll : 0.0
    }
});

// 5. 事件
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0),
    orientation : {
        heading : Cesium.Math.toRadians(175.0),
        pitch : Cesium.Math.toRadians(-35.0),
        roll : 0.0
    }
  	duration: 5, // 设置飞行持续时间,默认值会根据距离计算
  	complete: function(){
  			// 到达位置后执行的回调函数
		},
    cancle: function(){
      	// 如果取消飞行则会调用此函数
    },
    pitchAdjustHeight: -90,  // 如果摄像机飞跃高于该值,则调整俯仰角度,并将地球保持在视域中
    maximumHeight: 5000,     // 相机最大飞行高度
    flyOverLongitude: 100    // 相机飞向目的地的过程中,必须强制经过东经100°子午线
});

viewBoundingSphere(boundingSphere, offset)

viewBoundingSphere与setView效果类似,都是将视域切换到目标点,没有飞行过程。但是两个针对的目标不同,或者说方法不同viewBoundingSphere针对模型的外接圆。所以viewBoundingSphere适合做室内的浏览,因为室内空间小,相机不易控制。而viewBoundingSphere可以将相机固定在定点上,视角绕点360°旋转,实现定点环游。BoundingSphere其实就是物体模型外接球。

lookAt(target, offset)

这个函数也是将视域固定在某个目标上,用户可以通过鼠标任意旋转视角方向,但是不会改变其位置。

js
// 1. Using a cartesian offset
const center = Cesium.Cartesian3.fromDegrees(-98.0, 40.0);
viewer.camera.lookAt(center, new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0));

// 2. Using a HeadingPitchRange offset
const center = Cesium.Cartesian3.fromDegrees(-72.0, 40.0);   // 设定相机目标点平面位置
const heading = Cesium.Math.toRadians(50.0);	 // 偏航角
const pitch = Cesium.Math.toRadians(-20.0);   // 俯仰角
const range = 5000.0;  // 距离目标点水平面距离
viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));