Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate left or right in Cesium Map based on view bounds

Want to mimic the left-right arrow keys in CesiumJS app similar to Google Earth navigation. Press right or left arrow keys should rotate the globe ~5% of the view bounds to the right or left, respectively. If zoomed out then it rotates a large extent and zoomed in rotates a smaller extent.

Already looked at the documentation for Viewer, Camera, Scene, etc. but it's not obvious how to do something that should be simple.

Able to rotate a fixed amount right or left but want to rotate amount based on the width in the view extent. How do you get the max extent top, left, right, bottom for the view in cesium?

var viewer = new Cesium.Viewer('cesiumContainer', {
  navigationHelpButton: false, animation: false, timeline: false
});
var camera = viewer.camera;
document.addEventListener('keydown', function(e) {
    setKey(e);
}, false);

function setKey(event) {  
 if (event.keyCode == 39) {  // right arrow 
  camera.rotateRight(Cesium.Math.toRadians(10.0));
 } else if (event.keyCode == 37) {  // left arrow
  camera.rotateLeft(Cesium.Math.toRadians(10.0));
 }
}

To test, visit SandCastle app and paste in the javascript snippet above. To activate the keyboard bindings, click full screen mode and the arrow keys will work.

Alternatively, the camera can be used to access positionCartographic, but this is only the cartographic position of the camera, not the view bounds.

  var positionCartographic = camera.positionCartographic;
  var height = positionCartographic.height;
  var lat = positionCartographic.latitude;              
  var lon = positionCartographic.longitude + Cesium.Math.toRadians(10.0);    
  camera.flyTo({
    destination: Cesium.Cartesian3.fromRadians(lon, lat, height),
    duration: 1.0
  });

Here a fixed angle is added to the center view point, but the angle needs to be a percentage of the difference between max and min longitude values in the view extent; e.g. angle = (maxLon - minLon) / 20

like image 400
CodeMonkey Avatar asked Feb 11 '16 00:02

CodeMonkey


1 Answers

You're in luck. The much-requested feature for Camera.computeViewRectangle was just added in Cesium 1.19, released about a week ago as of this writing. Here it is in action.

Note that browsers are generally not comfortable with embedded documents receiving keypress events, so this doesn't work too well as a Stack Snippet. You have to click the magnifying-glass geocoder search box (to get a text entry field), that can receive arrow key events, and then this demo will work. Outside of Stack Overflow, you may find it easier to receive keypresses.

var viewer = new Cesium.Viewer('cesiumContainer', {
    navigationHelpButton: false, animation: false, timeline: false
});

var camera = viewer.camera;

document.addEventListener('keydown', function(e) {
    setKey(e);
}, false);

function setKey(event) {
    var horizontalDegrees = 10.0;
    var verticalDegrees = 10.0;
    var viewRect = camera.computeViewRectangle();
    if (Cesium.defined(viewRect)) {
        horizontalDegrees *= Cesium.Math.toDegrees(viewRect.east - viewRect.west) / 360.0;
        verticalDegrees *= Cesium.Math.toDegrees(viewRect.north - viewRect.south) / 180.0;
    }
    
    if (event.keyCode === 39) {  // right arrow 
        camera.rotateRight(Cesium.Math.toRadians(horizontalDegrees));
    } else if (event.keyCode === 37) {  // left arrow
        camera.rotateLeft(Cesium.Math.toRadians(horizontalDegrees));
    } else if (event.keyCode === 38) {  // up arrow
        camera.rotateUp(Cesium.Math.toRadians(verticalDegrees));
    } else if (event.keyCode === 40) {  // down arrow
        camera.rotateDown(Cesium.Math.toRadians(verticalDegrees));
    }
}
html, body, #cesiumContainer {
  width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
  font-family: sans-serif;
}
<link href="http://cesiumjs.org/releases/1.19/Build/Cesium/Widgets/widgets.css" 
      rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.19/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
like image 63
emackey Avatar answered Oct 01 '22 10:10

emackey