Cesium中文網(wǎng):http://cesiumcn.org/ | 國(guó)內(nèi)快速訪問(wèn):http://cesium.coinidea.com/
Camera
CesiumJS中的Camera控制場(chǎng)景的視圖选侨。有很多方法可以操作Camera,如旋轉(zhuǎn)(rotate)阎姥、縮放(zoom)捧灰、平移(pan)和飛到目的地(flyTo)互妓。CesiumJS有鼠標(biāo)和觸摸事件用來(lái)處理與Camrea的交互,還有API來(lái)以編程方式操作攝像機(jī)。了解如何使用Camera API和自定義相機(jī)控制(Camera controls)儡羔。
默認(rèn)Camera行為
打開Sandcastle中的Hello World樣例用來(lái)體驗(yàn)?zāi)J(rèn)的相機(jī)控制。默認(rèn)操作方式如下:
鼠標(biāo)操作 | 3D | 2D | Columbus視角 |
---|---|---|---|
Left click + drag | Rotate around the globe | Translate over the map | Translate over the map |
Right click + drag | Zoom in and out | Zoom in and out | Zoom in and out |
Middle wheel scrolling | Zoom in and out | Zoom in and out | Zoom in and out |
Middle click + drag | Tilt the globe | No action | Tilt the map |
鼠標(biāo)操作 | 3D | 2D | Columbus視角 |
---|---|---|---|
左鍵 + 拖拽 | 旋轉(zhuǎn)地球 | 在地圖上移動(dòng) | 在地圖上移動(dòng) |
右鍵 + 拖拽 | 縮放 | 縮放 | 縮放 |
中鍵滾輪 | 縮放 | 縮放 | 縮放 |
中鍵 + 拖拽 | 傾斜地球 | 無(wú)操作 | 傾斜地球 |
使用setView函數(shù)設(shè)置Camera的位置和方向璧诵。destination可以是Cartesian3或Rectangle汰蜘,orientation可以是heading/pitch/roll或direction/up。航向角之宿、俯仰角和橫滾角以弧度定義族操。航向角是從正角度向東增加的局部北向旋轉(zhuǎn)。俯仰角是指從局部的東北平面開始的旋轉(zhuǎn)比被。正俯仰角在平面上方色难。負(fù)俯仰角在平面以下。很滾叫是圍繞局部東軸應(yīng)用的第一個(gè)旋轉(zhuǎn)等缀。
camera.setView({
destination : new Cesium.Cartesian3(x, y, z),
orientation: {
heading : headingAngle,
pitch : pitchAngle,
roll : rollAngle
}
});
viewer.camera.setView({
destination : Cesium.Rectangle.fromDegrees(west, south, east, north),
orientation: {
heading : headingAngle,
pitch : pitchAngle,
roll : rollAngle
}
});
上述的所有參數(shù)都是可選的枷莉。如果未指定,參數(shù)值將被設(shè)為默認(rèn)值用戶當(dāng)前Camera的位置和方向尺迂。
自定義Camera鼠標(biāo)或者鍵盤事件
創(chuàng)建我們自己的事件控制笤妙,根據(jù)鼠標(biāo)的朝向用于控制Camera的朝向,鍵盤的按鍵控制Camera向前噪裕、向左蹲盘、向右、向上膳音,以及向下召衔。首先從禁用默認(rèn)事件操作開始。在(javascript var viewe=...
)之后添加下列代碼:
var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.onclick = function() {
canvas.focus();
};
var ellipsoid = viewer.scene.globe.ellipsoid;
// disable the default event handlers
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;
創(chuàng)建變量記錄當(dāng)前鼠標(biāo)位置祭陷,然后標(biāo)記并跟隨Camera移動(dòng)軌跡:
var startMousePosition;
var mousePosition;
var flags = {
looking : false,
moveForward : false,
moveBackward : false,
moveUp : false,
moveDown : false,
moveLeft : false,
moveRight : false
};
添加一個(gè)事件控制用戶設(shè)置標(biāo)記苍凛,當(dāng)鼠標(biāo)左鍵被點(diǎn)擊的時(shí)候,用于記錄當(dāng)前鼠標(biāo)的位置:
var handler = new Cesium.ScreenSpaceEventHandler(canvas);
handler.setInputAction(function(movement) {
flags.looking = true;
mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
handler.setInputAction(function(movement) {
mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function(position) {
flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
創(chuàng)建鍵盤事件控制用戶切換Camera移動(dòng)標(biāo)記颗胡。我們?yōu)橄铝邪存I和行為設(shè)置了標(biāo)記:
- w Camera向前毫深。
- s Camera向后。
- a Camera向左毒姨。
- d Camera向右哑蔫。
- q Camera向上。
- e Camera向下。
function getFlagForKeyCode(keyCode) {
switch (keyCode) {
case 'W'.charCodeAt(0):
return 'moveForward';
case 'S'.charCodeAt(0):
return 'moveBackward';
case 'Q'.charCodeAt(0):
return 'moveUp';
case 'E'.charCodeAt(0):
return 'moveDown';
case 'D'.charCodeAt(0):
return 'moveRight';
case 'A'.charCodeAt(0):
return 'moveLeft';
default:
return undefined;
}
}
document.addEventListener('keydown', function(e) {
var flagName = getFlagForKeyCode(e.keyCode);
if (typeof flagName !== 'undefined') {
flags[flagName] = true;
}
}, false);
document.addEventListener('keyup', function(e) {
var flagName = getFlagForKeyCode(e.keyCode);
if (typeof flagName !== 'undefined') {
flags[flagName] = false;
}
}, false);
現(xiàn)在當(dāng)標(biāo)記表明事件發(fā)生為true是闸迷,我們更新(update)camera嵌纲。我們新增**onTick的監(jiān)聽事件在clock中:
viewer.clock.onTick.addEventListener(function(clock) {
var camera = viewer.camera;
});
接下來(lái),我們讓Camera指向鼠標(biāo)指向的方向腥沽。在變量聲明之后添加下列代碼到事件監(jiān)聽函數(shù):
if (flags.looking) {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
// Coordinate (0.0, 0.0) will be where the mouse was clicked.
var x = (mousePosition.x - startMousePosition.x) / width;
var y = -(mousePosition.y - startMousePosition.y) / height;
var lookFactor = 0.05;
camera.lookRight(x * lookFactor);
camera.lookUp(y * lookFactor);
}
lookRight和lookUp只需要一個(gè)角度參數(shù)用于表示旋轉(zhuǎn)的角度逮走。我們將鼠標(biāo)坐標(biāo)轉(zhuǎn)換為范圍(-1.0,1.0)今阳,坐標(biāo)(0.0师溅,0.0)位于畫布的中心。鼠標(biāo)距中心的距離決定了旋轉(zhuǎn)的速度盾舌∧钩簦靠近中心的位置移動(dòng)Camera的速度較慢,而遠(yuǎn)離中心的位置移動(dòng)Camera的速度較快妖谴。
最后窿锉,添加代碼用于移動(dòng)Camera的位置。然后添加下列代碼到事件響應(yīng)函數(shù):
// Change movement speed based on the distance of the camera to the surface of the ellipsoid.
var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
var moveRate = cameraHeight / 100.0;
if (flags.moveForward) {
camera.moveForward(moveRate);
}
if (flags.moveBackward) {
camera.moveBackward(moveRate);
}
if (flags.moveUp) {
camera.moveUp(moveRate);
}
if (flags.moveDown) {
camera.moveDown(moveRate);
}
if (flags.moveLeft) {
camera.moveLeft(moveRate);
}
if (flags.moveRight) {
camera.moveRight(moveRate);
}
moveForward膝舅、moveBackward嗡载、moveUp、moveDown仍稀、moveLeft和moveRight方法只需要一個(gè)距離參數(shù)(米)用于移動(dòng)Camera的距離洼滚。當(dāng)每一個(gè)按鍵被按下時(shí),Camera就會(huì)在球體表面移動(dòng)固定的距離琳轿。Camera離地面越近判沟,移動(dòng)的速度就越慢。
完整的代碼如下:
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.onclick = function() {
canvas.focus();
};
var ellipsoid = viewer.scene.globe.ellipsoid;
// disable the default event handlers
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;
var startMousePosition;
var mousePosition;
var flags = {
looking : false,
moveForward : false,
moveBackward : false,
moveUp : false,
moveDown : false,
moveLeft : false,
moveRight : false
};
var handler = new Cesium.ScreenSpaceEventHandler(canvas);
handler.setInputAction(function(movement) {
flags.looking = true;
mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
handler.setInputAction(function(movement) {
mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function(position) {
flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
function getFlagForKeyCode(keyCode) {
switch (keyCode) {
case 'W'.charCodeAt(0):
return 'moveForward';
case 'S'.charCodeAt(0):
return 'moveBackward';
case 'Q'.charCodeAt(0):
return 'moveUp';
case 'E'.charCodeAt(0):
return 'moveDown';
case 'D'.charCodeAt(0):
return 'moveRight';
case 'A'.charCodeAt(0):
return 'moveLeft';
default:
return undefined;
}
}
document.addEventListener('keydown', function(e) {
var flagName = getFlagForKeyCode(e.keyCode);
if (typeof flagName !== 'undefined') {
flags[flagName] = true;
}
}, false);
document.addEventListener('keyup', function(e) {
var flagName = getFlagForKeyCode(e.keyCode);
if (typeof flagName !== 'undefined') {
flags[flagName] = false;
}
}, false);
viewer.clock.onTick.addEventListener(function(clock) {
var camera = viewer.camera;
if (flags.looking) {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
// Coordinate (0.0, 0.0) will be where the mouse was clicked.
var x = (mousePosition.x - startMousePosition.x) / width;
var y = -(mousePosition.y - startMousePosition.y) / height;
var lookFactor = 0.05;
camera.lookRight(x * lookFactor);
camera.lookUp(y * lookFactor);
}
// Change movement speed based on the distance of the camera to the surface of the ellipsoid.
var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
var moveRate = cameraHeight / 100.0;
if (flags.moveForward) {
camera.moveForward(moveRate);
}
if (flags.moveBackward) {
camera.moveBackward(moveRate);
}
if (flags.moveUp) {
camera.moveUp(moveRate);
}
if (flags.moveDown) {
camera.moveDown(moveRate);
}
if (flags.moveLeft) {
camera.moveLeft(moveRate);
}
if (flags.moveRight) {
camera.moveRight(moveRate);
}
});
Camera
Camera表示Camera當(dāng)前位置崭篡、方向、參考幀和視圖截錐的狀態(tài)吧秕。上面的Camera向量在每幀中都是正交的琉闪。
move和zoom**函數(shù)平移Camera的位置按照它的方向或指定的方向矢量。方向保持固定不變砸彬。
look和twist**函數(shù)旋轉(zhuǎn)Camera的方向比如向上颠毙、或向右矢量。位置保持固定不變砂碉。
rotate*函數(shù)玄幻位置和方向基于給定矢量蛀蜜。
函數(shù)設(shè)置Camera給定范圍或位置和目標(biāo)的Camera位置和方向。例如:
var west = Cesium.Math.toRadians(-77.0);
var south = Cesium.Math.toRadians(38.0);
var east = Cesium.Math.toRadians(-72.0);
var north = Cesium.Math.toRadians(42.0);
var extent = new Cesium.Extent(west, south, east, north);
camera.viewExtent(extent, Cesium.Ellipsoid.WGS84);
創(chuàng)建變量ray增蹭,通過(guò)像素拾取Camera的位置滴某。該方法可用于拾取,例如:
// find intersection of the pixel picked and an ellipsoid
var ray = camera.getPickRay(mousePosition);
var intersection = Cesium.IntersectionTests.rayEllipsoid(ray, Cesium.Ellipsoid.WGS84);
Screen space camera controller
ScreenSpaceCameraController將用戶輸入(如鼠標(biāo)和觸摸)從窗口坐標(biāo)轉(zhuǎn)換為Camera運(yùn)動(dòng)。它包含用于啟用和禁用不同類型輸入霎奢、修改慣性量以及最小和最大縮放距離的屬性户誓。
資源
可在Sandcastle中查看camera樣例代碼:
API文檔:
Cesium中文網(wǎng)交流QQ群:807482793
Cesium中文網(wǎng):http://cesiumcn.org/ | 國(guó)內(nèi)快速訪問(wèn):http://cesium.coinidea.com/