在二维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是指相机位置的三维坐标(可以用经纬度和大地高表达)。
示例:
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有多种操作相机的方法。常见的有setView
、flyTo
、viewBoundingSphere
、looAt
等等。
setView(options)
通过设定目标点三维坐标(经纬度,高度)以及视线方向,快速的将视角调整到定义的可视区域。没有中间动画过程。
// 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则是将摄像机从当前位置移动到新位置,并且具有逐步切换的动画效果,可设置飞行时间。相机会根据当前视点位置自动设定飞行速度和飞行路线,视线巡游式视域切换。
// 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)
这个函数也是将视域固定在某个目标上,用户可以通过鼠标任意旋转视角方向,但是不会改变其位置。
// 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));