一、camera类介绍
Camera在Cesium中是用来控制场景的视图,很多方法可以操作Camera,例如,旋转(rotate)、缩放(zoom)、平移(pan)、飞到目的地(flyTo)。CesiumJS有鼠标和触摸事件用来处理与Camrea的交互,还有API来以编程方式操作摄像机。
了解如何使用Camera API和自定义相机控制(Camera controls)。
二、Cesium的视角坐标系统——scene.camera
1.坐标系统
- Cartesian3:三维笛卡尔(直角)坐标系,地心为原点。
- Cartographic:经纬度及wgs84的高程来定位。
- HeadingPitchRoll:在ENU(East-North-Up)坐标系中,相对坐标轴的(一般用于camera相机位置设置)。
- Quaternion:使用四维坐标描述的三维旋转。
每一种坐标系统,Cesium都给出了介绍,https://cesium.com/docs/cesiumjs-ref-doc/Camera.html?classFilter=camera,主要看参数及单位。
例:

1 var camera = new Cesium.Camera(scene); 2 camera.position = new Cesium.Cartesian3(); 3 camera.direction = Cesium.Cartesian3.negate(Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3());
2.各类坐标系统的转换
(1)单位,Cesium.Math
- Math.ToRadians(度数) —>弧度
- Math.toDegrees(弧度)—>角度
(2)heading、pitch、roll(单位是弧度单位)
- heading为0度对应的radians,相机没有左右摆头。
- pitch为-90度对应的radians,即相机是正俯视。
- roll一般为0,不常见。
(3)改变homeButton的初始位置

1 //设置想要的位置 2 var homeCameraView={destination:new Cesium.Cartesian3.fromDegrees(113,23,1000000), 3 orientation:{ 4 heading:0, 5 pitch:-1.5707963267948966, 6 roll:0 7 }}; 8 9 //过程10秒 10 homeCameraView.duration = 10.0; 11 //飞行的最大高度,设置很高时就会先很高然后下降 12 homeCameraView.maximumHeight = 1000000; 13 //如果飞的太高则自动纠正,保障地球在视角内 14 homeCameraView.pitchAdjustHeight = 1000000; 15 16 homeCameraView.endTransform = Cesium.Matrix4.IDENTITY; 17 18 //改变homeButton的初始位置 19 viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) { 20 e.cancel = true; 21 viewer.scene.camera.flyTo(homeCameraView); 22 });
三、camera相机实例
1、Camera.html

1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 <meta name="viewport" 8 content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no"> 9 <meta name="description" content="Fly to a specified location or view a geographic rectangle."> 10 <meta name="cesium-sandcastle-labels" content="Beginner, Tutorials, Showcases"> 11 <title>Cesium App</title> 12 <script src="./scripts/Build/Cesium/Cesium.js"></script> 13 <link rel="stylesheet" href="./scripts/Build/Cesium/Widgets/widgets.css"> 14 <style> 15 @import url("./scripts/Build/Cesium/Widgets/widgets.css"); 16 17 html, 18 body { 19 height: 100%; 20 width: 100%; 21 margin: 0px; 22 padding: 0px; 23 overflow: hidden; 24 background: #000; 25 font-family: sans-serif; 26 } 27 28 .fullSize{ 29 display: block; 30 position: absolute; 31 top: 0; 32 left: 0; 33 border: none; 34 width: 100%; 35 height: 100%; 36 } 37 38 #toolbar{ 39 margin: 5px; 40 padding: 2px 5px; 41 position: absolute; 42 } 43 </style> 44 </head> 45 46 <body> 47 <div id="cesiumContainer" class="fullSize"></div> 48 <div id="toolbar"> 49 <select id="camera_select", class="cesium-button"> 50 <option value="undefined"> 51 相机选项 52 </option> 53 <option value="undefined"> 54 飞行到某一点——杭州萧山机场 55 </option> 56 <option value="undefined"> 57 飞行到某区域——杭州市 58 </option> 59 <option value="undefined"> 60 设置相机点——萧山机场 61 </option> 62 <option value="undefined"> 63 设置相机区域——广州市 64 </option> 65 <option value="undefined"> 66 从广州飞往杭州 67 </option> 68 </select> 69 </div> 70 71 <script src="Camera.js"></script> 72 </body> 73 74 </html>
2、Camera.js

1 //添加你的cesium token 2 Cesium.Ion.defaultAccessToken = '你的token'; 3 4 //使用严格模式 5 'use strict' 6 7 //默认bing影像地图 8 var viewer = new Cesium.Viewer('cesiumContainer',{ 9 imageryProvider: Cesium.createWorldImagery({ 10 style: Cesium.IonWorldImageryStyle.AERIAL 11 }), 12 baseLayerPicker: false 13 }); 14 15 //根据id获取HTML页面的下拉列表框控件camera_select 16 var camera_select = document.getElementById("camera_select"); 17 18 if(camera_select){ 19 camera_select.onchange = function gradeChange(){ 20 switch(camera_select.selectedIndex){ 21 case 1: 22 viewer.camera.flyTo({ 23 destination: Cesium.Cartesian3.fromDegrees(120.01131, 29.96809, 1996.44), 24 orientation:{ 25 heading: Cesium.Math.toRadians(0.0), 26 pitch: Cesium.Math.toRadians(-90.0), 27 roll: Cesium.Math.toRadians(0.0) 28 } 29 }); 30 break; 31 case 2: 32 viewer.camera.flyTo({ 33 destination: Cesium.Rectangle.fromDegrees(118.02126, 28.28773, 120.21369, 30.15177) 34 }); 35 break; 36 case 3: 37 viewer.camera.setView({ 38 destination: Cesium.Cartesian3.fromDegrees(120.35, 30.21231, 243.84), 39 orientation: { 40 heading: Cesium.Math.toRadians(0.0), 41 pitch: Cesium.Math.toRadians(-90.0), 42 roll: Cesium.Math.toRadians(0.0) 43 } 44 }); 45 break; 46 case 4: 47 viewer.camera.setView({ 48 destination: Cesium.Rectangle.fromDegrees(113.33411, 23.43951, 113.92169, 23.58429) 49 }); 50 break; 51 case 5: { 52 var whdxOptions = { 53 destination: Cesium.Cartesian3.fromDegrees(114.13966, 23.61942, 5699.76), 54 duration: 5, 55 orientation: { 56 heading: Cesium.Math.toRadians(0.0), 57 pitch: Cesium.Math.toRadians(-90.0), 58 roll: Cesium.Math.toRadians(0.0) 59 } 60 }; 61 var hzkjdxOptions = { 62 destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0), 63 orientation: { 64 heading: Cesium.Math.toRadians(0.0), 65 pitch: Cesium.Math.toRadians(-90.0), 66 roll: Cesium.Math.toRadians(0.0) 67 }, 68 duration: 5, 69 }; 70 whdxOptions.complete = function () { 71 setTimeout(function () { 72 viewer.camera.flyTo(hzkjdxOptions); 73 }, 1000); 74 }; 75 viewer.camera.flyTo(whdxOptions); 76 } 77 break; 78 default: 79 break; 80 } 81 } 82 }
3、camera常见函数
(1)Cesium.Camera的flyTo()函数,设置相机镜头逐渐从当前位置飞行到某一点。它的属性有:
- destination:相机的镜头位置。
- orientation:相机的姿态。
- duration:两个点之间飞行的间隔,单位(s)
- complete:当飞行完成需要执行的函数。
- cancel:当飞行取消需要执行的函数。
- endTransform:变换矩阵,表示飞行结束时,摄像机所在的参考坐标系。
- maximumHeight:飞行的最大高度。
- pitchAdjustHeigh:当是从上往下看时,调整pitch,保持视野。
- flyOverLongitude:地球上两点之间总有两条路。此选项强制相机选择战斗方向,以飞越该经度。
- flyOverLongitudeWeight:飞越指定的经度,只在该经度不长于短航程乘以经度的情况下。
- convert:是否将目标从世界坐标转换为场景坐标(仅在不使用3D时相关)。默认值为true。
- easingFunction:控制如何在飞行期间内插入时间。

1 /* 2 将相机的位置移动到经纬度位置(120.01131, 29.96809),离地面1996.44米的点;航向角(heading)设置为0度,俯仰角(pitch)设置为-90度,滚转角(roll)设置为0度 3 */ 4 viewer.camera.flyTo({ 5 destination: Cesium.Cartesian3.fromDegrees(120.01131, 29.96809, 1996.44), 6 orientation: { 7 heading: Cesium.Math.toRadians(0.0), 8 pitch: Cesium.Math.toRadians(-90.0), 9 roll: Cesium.Math.toRadians(0.0) 10 } 11 });
(2)new Cesium.HeadingPitchRange(heading, pitch, range)
航向角(heading)是绕Z后负方向旋转的角度,俯仰角(pitch)是绕Y轴负方向旋转的角度,滚转角(roll)是绕X轴正方向旋转的角度。
X、Y、Z轴指的是基于相机的视空间坐标系,类似于一种北东地站心坐标系(NED)坐标系,XYZ轴指的正是这个视空间坐标系的XYZ轴。在这个视空间坐标系中,Z轴垂直球面向下(Down),Y轴沿纬线指东(East),X轴沿经线向北(North),而位于视空间坐标系原点的相机的姿态为由南看向北。在这种情况下,只需要使相机绕Y轴正向旋转90度,也就是俯仰角(pitch)设为90,就可以得到视线垂直于地图,东西南北向正常的视图。
(3)flyTo()函数另外作用:根据设定的范围显示视图。比如,加载的三维模型的范围,一个地区的范围。只需要给位置参数destination传入一个Cesium.Rectangle对象。

1 viewer.camera.flyTo({ 2 destination: Cesium.Rectangle.fromDegrees(118.02126, 28.28773, 120.21369, 30.15177) 3 });
(4)flyTo()函数还可以传入一个配置项complete,可以给其设定一个飞行结束后再运行的函数,通过这个配置项可以实现两地或多地飞行。

1 /* 2 分别定义了两个飞行配置项whdxOptions和hzkjdxOptions,并且给whdxOptions的complete项配置了一个函数,表示完成1S之后,自动进行hzkjdxOptions的飞行 3 */ 4 var whdxOptions = { 5 destination: Cesium.Cartesian3.fromDegrees(114.13966, 23.61942, 5699.76), 6 duration: 5, 7 orientation: { 8 heading: Cesium.Math.toRadians(0.0), 9 pitch: Cesium.Math.toRadians(-90.0), 10 roll: Cesium.Math.toRadians(0.0) 11 } 12 }; 13 var hzkjdxOptions = { 14 destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0), 15 orientation: { 16 heading: Cesium.Math.toRadians(0.0), 17 pitch: Cesium.Math.toRadians(-90.0), 18 roll: Cesium.Math.toRadians(0.0) 19 }, 20 duration: 5, 21 }; 22 whdxOptions.complete = function () { 23 setTimeout(function () { 24 viewer.camera.flyTo(hzkjdxOptions); 25 }, 1000); 26 }; 27 viewer.camera.flyTo(whdxOptions);
(5)setView()函数。
设置当前视图通过setView()函数实现的。跟flyTo()最大的不同是没有持续时间,没有飞行过程,是立即生效的。