Camera

CesiumJS 中的相机控制场景的视图。 有很多操作相机的方法,例如旋转,缩放,平移和飞到目的地。 CesiumJS 具有鼠标和触摸事件处理程序以与相机进行交互,并具有以编程方式操作相机的API。 了解如何使用 Camera API 和自定义相机控件。


Default camera behavior

在 Sandcastle 中打开 Hello World 示例,以浏览默认的相机控件。 默认值为:

Mouse Action3D2DColumbus View
Left click + dragRotate around the globeTranslate over the mapTranslate over the map
Right click + dragZoom in and outZoom in and outZoom in and out
Middle wheel scrollingZoom in and outZoom in and outZoom in and out
Middle click + dragTilt the globeNo actionTilt the map

使用 setView 功能以编程方式设置摄像机的位置和方向。 destination 可以是 Cartesian3Rectangle ,方向可以是航向/俯仰/滚动或方向/向上。 航向角,俯仰角和横滚角以弧度定义。 航向是从局部北向旋转,其中正角向东增加。 俯仰是从本地东西向平面的旋转。 正俯仰角在平面上方。 负俯仰角在平面下方。 横摇是绕局部东轴应用的第一次旋转。

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 or 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);

现在,当指示事件发生的标志为true时,我们想更新摄像机。 我们可以在时钟上向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);
}

lookRightlookUp 方法采用一个以弧度为单位的参数,即旋转角度。 我们将鼠标坐标转换为(-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);
}

moveForwardmoveBackwardmoveUpmoveDownmoveLeftmoveRight 方法采用以米为单位的单个参数来移动照相机。照相机将在其上移动的距离 每次按键操作都会随着相机到椭圆表面的距离的变化而变化,相机越靠近表面,每次按键移动的速度就越慢。

完整的代码如下:

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 代表摄影机当前位置,方向,参考系和视锥的状态。 上面的摄像机矢量在每个帧中都是正交的。

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);

Screen space camera controller

ScreenSpaceCameraController 将用户输入(例如鼠标和触摸)从窗口坐标转换为相机运动。 它包含用于启用和禁用不同类型的输入,修改惯量以及最小和最大缩放距离的属性。


Resources

查看Sandcastle中的相机示例:

  • Camera Tutorial - 本教程中的代码示例。
  • Camera - 可以飞到特定位置,查看范围并设置相机参考系的代码示例。

另外,请查阅参考文档:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Camera Stream是一种用于实时传输摄像机图像的技术,通常用于视频流应用,如远程监控、无人驾驶车辆和机器人等领域。它可以将摄像机拍摄的图像实时传输到其他设备或网络,以便进行实时监控或分析。 Camera Stream的实现通常涉及到硬件和软件的结合。在硬件方面,摄像机需要能够输出高质量的图像,并且需要配备适当的编码器以将图像数据转换为适合传输的格式。在软件方面,需要实现适当的协议和算法来接收摄像机数据、进行传输和处理。 Camera Stream通常使用网络协议进行传输,如TCP/IP、UDP、HTTP等。这些协议提供了可靠的数据传输机制,以确保图像数据的实时性和完整性。此外,Camera Stream还可能需要使用一些编解码技术来优化图像数据的大小,以便在有限带宽下实现高效的传输。 使用Camera Stream可以带来许多优势。首先,它提供了实时的视频流,有助于实时监控和安全应用。其次,它可以帮助实现无人驾驶车辆和机器人的自主导航和决策,从而提高其效率和安全性。最后,Camera Stream还可以用于远程医疗、教育等领域,为远程协作和交流提供了便利。 需要注意的是,Camera Stream的实现和应用还受到许多因素的影响,如网络条件、设备性能和安全性等。因此,在使用Camera Stream时需要根据具体情况进行适当的调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高建伟-joe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值