一、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()最大的不同是沒有持續時間,沒有飛行過程,是立即生效的。