Cesium中文教程-相机(Camera)

目录

快速开始(Quick start)

自定义相机鼠标/键盘事件(Custom Camera mouse/keyboard events)

相机(Camera)

屏幕空间相机控制(Screen space camera controller)

资源(Resources)


速开始(Quick start)

Cesium相机控制着场景中的景象。有许多方法操作相机,例如旋转、缩放、平移和飞向目标。Cesium有默认的鼠标和触摸事件处理机制来与相机进行交互,以及程序化操作相机的API。本章教程介绍相机概念和相关的Cesium API。

让我们从示例开始,打开沙堡中的Hello W  orld。默认情况下,场景处理相机鼠标和触摸的输入:

  • 左点击并拖动-围绕3D球旋转相机,在2D和哥伦布视图中的地图表面转换相机;
  • 右点击并拖动-缩放相机;
  • 中间滚轮转动-也可以缩放相机;
  • 中间点击并拖动-围绕球表面点旋转相机。

我们可以用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  
    }  
});  

自定义相机鼠标/键盘事件(Custom Camera mouse/keyboard events)

我们创建自己的事件处理,其让相机朝向鼠标的方向,按下键向前、向后、向左、向右、向上和向下移动。让我们从禁止默认事件处理开始。添加如下的代码(在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);  

为相机移动创建键盘事件处理器来切换标记。我们将为下面的按键和行为设置标记:

  • w 向前移动相机;
  • s 向后移动相机;
  • a 向左移动相机;
  • d 向右移动相机;
  • q 向上移动相机;
  • e 向下移动相机。
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)。

相机(Camera)

The相机(Camera)表示相机当前的位置、方向、参考帧和视图截锥体(view frustum)的状态。

移动(move*)和变焦(zoom*)函数沿着相机方向或给定的矢量移动其位置,方向不变。

Cesium中文教程-相机(Camera)_第1张图片

look*和twist*函数是关于方向的,向上或向右旋转方向。保持位置不变。

Cesium中文教程-相机(Camera)_第2张图片

rotate*函数以给定矢量旋转位置和方位。

Cesium中文教程-相机(Camera)_第3张图片

注意:上面说到的相机矢量。

  • 设置给定范围或位置和目标的相机位置和方向。例如:
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);  
  • 从相机位置通过像素创建光线。这对于picking是有用的,例如:
// 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将用户的输入(像鼠标和触摸)从窗口坐标转换为相机运动。它含有用于启用/禁用不同类型输入、修改惯性量、最小化和最大化缩放距离的属性。

资源(Resources)

查看沙堡中的相机实例:

  • 相机教程(Camera Tutorial)-本章代码示例;
  • 相机(Camera)-飞到位置、视图范围和设置相机参考帧代码示例。

也可以查看参考文档:

  • 相机(Camera);
  • ScreenSpaceCameraController。

你可能感兴趣的:(Cesium中文教程,Cesium中文教程,javascript)