cesium鼠标控制键盘_Cesium中级教程3 - Camera - 相机(摄像机)

Camera

CesiumJS中的Camera控制场景的视图。有很多方法可以操作Camera,如旋转(rotate)、缩放(zoom)、平移(pan)和飞到目的地(flyTo)。CesiumJS有鼠标和触摸事件用来处理与Camrea的交互,还有API来以编程方式操作摄像机。了解如何使用Camera API和自定义相机控制(Camera controls)。

默认Camera行为

打开Sandcastle中的Hello World样例用来体验默认的相机控制。默认操作方式如下:

鼠标操作

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

鼠标操作

3D

2D

Columbus视角

左键 + 拖拽

旋转地球

在地图上移动

在地图上移动

右键 + 拖拽

缩放

缩放

缩放

中键滚轮

缩放

缩放

缩放

中键 + 拖拽

倾斜地球

无操作

倾斜地球

使用setView函数设置Camera的位置和方向。destination可以是Cartesian3或Rectangle,orientation可以是heading/pitch/roll或direction/up。航向角、俯仰角和横滚角以弧度定义。航向角是从正角度向东增加的局部北向旋转。俯仰角是指从局部的东北平面开始的旋转。正俯仰角在平面上方。负俯仰角在平面以下。很滚叫是围绕局部东轴应用的第一个旋转。

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的位置和方向。

自定义Camera鼠标或者键盘事件

创建我们自己的事件控制,根据鼠标的朝向用于控制Camera的朝向,键盘的按键控制Camera向前、向左、向右、向上,以及向下。首先从禁用默认事件操作开始。在(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;

创建变量记录当前鼠标位置,然后标记并跟随Camera移动轨迹:

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

创建键盘事件控制用户切换Camera移动标记。我们为下列按键和行为设置了标记:

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

现在当标记表明事件发生为true是,我们更新(update)camera。我们新增*onTick*的监听事件在clock中:

viewer.clock.onTick.addEventListener(function(clock) {

var camera = viewer.camera;

});

接下来,我们让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)位于画布的中心。鼠标距中心的距离决定了旋转的速度。靠近中心的位置移动Camera的速度较慢,而远离中心的位置移动Camera的速度较快。

最后,添加代码用于移动Camera的位置。然后添加下列代码到事件响应函数:

// 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方法只需要一个距离参数(米)用于移动Camera的距离。当每一个按键被按下时,Camera就会在球体表面移动固定的距离。Camera离地面越近,移动的速度就越慢。

完整的代码如下:

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当前位置、方向、参考帧和视图截锥的状态。上面的Camera向量在每帧中都是正交的。

move和zoom函数平移Camera的位置按照它的方向或指定的方向矢量。方向保持固定不变。

95c3d6b83ce5ddfee7ab921241db2da9.png

look和twist函数旋转Camera的方向比如向上、或向右矢量。位置保持固定不变。

dabb0272cf7bc5145fd1c3062e7aa312.png

rotate*函数玄幻位置和方向基于给定矢量。

ea3a3f86cdd2bbb3c1a2b70afc3fe446.png

函数设置Camera给定范围或位置和目标的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);

创建变量ray,通过像素拾取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将用户输入(如鼠标和触摸)从窗口坐标转换为Camera运动。它包含用于启用和禁用不同类型输入、修改惯性量以及最小和最大缩放距离的属性。

资源

可在Sandcastle中查看camera样例代码:

API文档:

Cesium中文网交流QQ群:807482793

本文由 admin 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。

可自由转载、引用,但需署名作者且注明文章出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows下统一mysql编码_mysql5.7 windows7编码统一utf-8

查看mysql数据编码登录mysql服务,查看mysql数据库默认的编码mysql> show variables like character%;---------------------------------------------------------------------------| Variable_name | Value |------------------------------------------------…

python读取配置文件失败原因_python读取配置文件报keyerror-文件路径不正确导致的错误...

- 在其他模块使用反射读取配置文件报错,但是在反射模块中读取GetData.check_list又是正确的反射模块如下:# get_data.pyfrom API_AUTO.p2p_project_7.tools import project_pathimport pandas as pdfrom API_AUTO.p2p_project_7.tools.read_config impor…

备忘录设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

打印机一直显示正在删除不掉怎么办?

1、停止打印服务,按WinR键打开运行对话框,然后输入“services.msc ” 打开任务管理。 找到“Print Spooler”,先停止该服务。 按WinR键打开运行对话框,然后输入“Spool” 回车打开“spool” 文件夹,打开“PRINTERS”文…

java 并发 面试_Java 并发基础常见面试题总结

1. 什么是线程和进程?1.1. 何为进程?进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM…

javafx动画_JavaFX:创建Sprite动画

javafx动画到目前为止,尽管我的大多数文章都涉及JavaFX属性和绑定,但是今天我想写一讲我也致力于JavaFX运行时的另一部分:动画API。 在本文中,我将解释如何在JavaFX中编写自定义动画,以及如何使用这种方法为Sprite动画…

FZU Problem 2238 Daxia Wzc's problem

Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题: Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(1)前n项和,得到新数列A(2); 接着让Daxia求出数列A(2)前n项和,得到新…

生成器设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

【转】从 ArcGIS for Desktop 发布地图服务

原文链接:http://resources.arcgis.com/zh-CN/help/tutorials/01z300000007000000.htm 本教程的目的是将地图服务直接从 ArcGIS for Desktop 发布到 ArcGIS for Server 中。本教程与名为“在 ArcMap 中准备您的 Web 地图”的上一教程类似,需要使用 ArcGI…

java 模块化osgi_OSGi简介–模块化Java

java 模块化osgiOSGi联盟是这种搁浅的管理机构,它始于1999年。其最初目标是为网络设备创建开放搁浅。 基于此思想,此规范也针对Java引入。 Eclipse在Java中是第一个。 他们于2004年6月推出了基于OSGi的Eclipse IDE。 OSGi是在Java中定义动态模块的方法。…

Train Problem I hdu 1022(栈)

http://acm.split.hdu.edu.cn/showproblem.php?pid1022 题意&#xff1a;给出火车的进站与出站顺序&#xff0c;判断是否可以按照给出的出站顺序出站。 #include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <…

Spring数据和Redis

本文是我们学院课程的一部分&#xff0c;标题为Redis NoSQL键值存储 。 这是Redis的速成班。 您将学习如何安装Redis并启动服务器。 此外&#xff0c;您将在Redis命令行中乱七八糟。 接下来是更高级的主题&#xff0c;例如复制&#xff0c;分片和集群&#xff0c;同时还介绍了…

史上最全的SpringMVC学习笔记

SpringMVC学习笔记---- 一、SpringMVC基础入门&#xff0c;创建一个HelloWorld程序 1.首先&#xff0c;导入SpringMVC需要的jar包。 2.添加Web.xml配置文件中关于SpringMVC的配置<!--configure the setting of springmvcDispatcherServlet and configure the mapping-->&…

shader weaver_Oracle通过邀请Weaver和Chin推动JavaFX向前发展

shader weaver昨天&#xff0c;我发布了愚人节帖子&#xff0c;内容涉及加入NASA协助探索红色大行星。 那篇文章与事实相距不远……美国宇航局开发的技术的所有细节都是100&#xff05;准确的。 哎呀&#xff0c;即使我辞职也是事实&#xff01; 唯一不正确的部分是我将加入的公…

mysql快速上手3

上一章给大家说的是数据库的视图&#xff0c;存储过程等等操作&#xff0c;这章主要讲索引&#xff0c;以及索引注意事项&#xff0c;如果想看前面的文章&#xff0c;url如下&#xff1a; mysql快速上手1mysql快速上手2索引简介 索引是对数据库表中一个或多个列&#xff08;例如…

python图像锐化_Python图像处理介绍--图像模糊与锐化

欢迎关注 “小白玩转Python”&#xff0c;发现更多 “有趣”引言在之前的文章中&#xff0c;我们讨论了边缘检测内核。在本文我们将讨论如何在图像上应用模糊与锐化内核&#xff0c;将这些内核应用到彩色图像上&#xff0c;同时保留核心图像。一如既往&#xff0c;我们从导入所…

Eclipse配置初始化(自用)

以上都是性能调优的配置&#xff0c;下面是其他常用的配置和优化 设置utf-8编码 window -> preferences -> General -> workplace中text file encoding改为utf-8 设置properties文件编码window -> preferences -> General -> Content Types —> Text —&g…

java bits_一段关于JAVA程序升级的问题(Changing bits)

展开全部import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JTextField;import javax.…

java合并两个有序链表_JS实现的合并两个有序链表算法示例

本文实例讲述了JS实现的合并两个有序链表算法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例&#xff1a;输入&#xff1a;1->2->4, 1->3->4输出&…

外墙设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …