目录
快速开始(Quick start)
自定义相机鼠标/键盘事件(Custom Camera mouse/keyboard events)
相机(Camera)
屏幕空间相机控制(Screen space camera controller)
资源(Resources)
Cesium相机控制着场景中的景象。有许多方法操作相机,例如旋转、缩放、平移和飞向目标。Cesium有默认的鼠标和触摸事件处理机制来与相机进行交互,以及程序化操作相机的API。本章教程介绍相机概念和相关的Cesium API。
让我们从示例开始,打开沙堡中的Hello W orld。默认情况下,场景处理相机鼠标和触摸的输入:
我们可以用setView函数程序化设置相机的位置和方位。参数是目的地和方位。位置可以是Cartesian3(笛卡尔)或Rectangle的实例,方位可以是偏航/俯仰/滚动或方向/向上。偏航、俯仰、滚动要求以弧度为单位。偏航围绕北向旋转,向东为正角并增加。俯仰围绕东北平面旋转,正俯仰角在平面上方,负俯仰在平面下方。滚动绕东向轴进行的第一次旋转。例如,像这样设置笛卡尔坐标:
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
}
});
所有参数是可选的,任何未定义参数的默认值是当前相机位置、偏航、俯仰和滚动。
常用的设置是相机直视球,并且偏航朝着北:
camera.setView({
destination : Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
orientation: {
heading : 0.0,
pitch : -Cesium.Math.PI_OVER_TWO,
roll : 0.0
}
});
我们创建自己的事件处理,其让相机朝向鼠标的方向,按下键向前、向后、向左、向右、向上和向下移动。让我们从禁止默认事件处理开始。添加如下的代码(在var viewer = …之后):
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);
现在,当标记表明一个事件真实发生时,我们想更新相机。我们可以向时钟onTick事件添加一个监听器,包含以下代码:
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);
}
lookRight和lookUp方法接收一个弧度为单位的参数,其表示旋转的角度。我们将鼠标坐标转换到范围(-1.0,1.0),并将坐标(0.0,0.0)转换为画布中心。鼠标离中心的距离决定了运行的速度。靠近中心的位置移动相机较慢,而远离中心的位置移动相机较快。
最后,让我们添加代码来移动相机的位置。同样添加到事件监听器函数中:
// 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方法接收一个米单位的参数,来移动相机。相机在每个按键上将移动的距离,随着相机到椭球面距离的变化而变化。相机离地面越近,按下每一个键的速度越慢。
完整代码如下:
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);
}
});
查看Sandcastle中全部示例(full example)。
The相机(Camera)表示相机当前的位置、方向、参考帧和视图截锥体(view frustum)的状态。
移动(move*)和变焦(zoom*)函数沿着相机方向或给定的矢量移动其位置,方向不变。
look*和twist*函数是关于方向的,向上或向右旋转方向。保持位置不变。
rotate*函数以给定矢量旋转位置和方位。
注意:上面说到的相机矢量。
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);
// find intersection of the pixel picked and an ellipsoid
var ray = camera.getPickRay(mousePosition);
var intersection = Cesium.IntersectionTests.rayEllipsoid(ray, Cesium.Ellipsoid.WGS84);
ScreenSpaceCameraController将用户的输入(像鼠标和触摸)从窗口坐标转换为相机运动。它含有用于启用/禁用不同类型输入、修改惯性量、最小化和最大化缩放距离的属性。
查看沙堡中的相机实例:
也可以查看参考文档: