Hands On

Now in 3D! – Learn How to Use the Camera in the New Javascript API 3.1

By Richard Süselbeck | 14 October 2019

The new version 3.1 of our JavaScript API brings a whole host of new exciting features, chief among them the arrival of vector tiles and a 3D renderer. This in turns means you are now longer limited to a top-down view of the map. Check this out.

example

In addition to moving the camera along two axes and zooming, you can now also rotate and tilt the it. It's a whole new world! Of course, this also raises the question: How do you do this?

First, the good news. You can still use setPosition() and setZoom() just as before. So after setting up a basic map (for example by using our examples in GitHub), you can get a close-up look of Terminal A at TXL airport using this code snippet.


  map.setCenter({lat: 52.5544, lng: 13.29036});
  map.setZoom(18.1);  
TXL

So far so good. The eagle-eyed among you may have spotted a tiny little difference, though. That's right, we've used a fractional zoom factor. With vector tiles there are no more preset zoom factors and you can zoom in to a very specific factor of 18.2817151. If that's your thing.

Now then, how do we tilt and rotate the camera? After all, that's really what we're here for. Well, to set how we look at the map we use the function ViewModel.setLookAtData. This function takes a look-at data set as described in ViewModel.ILookAt as a parameter. The data set can contain any or all of the following properties: position, zoom, heading, tilt and bounds.


  map.getViewModel().setLookAtData({
      position: {lat: 52.5544, lng: 13.29036}, 
      zoom: 18.1});
TXL

As we can see, we get the exact some view as before. Now, let's move on to the interesting parts, namely heading and tilt.

The heading property allows us to rotate the camera. Heading can be a value from 0 to 360, with 0 indicating that the camera is looking from the North, 90 from the East, 180 from the South and 270 from the West. This means you normal map with north at the top, would have a heading of 180. Let’s use 0 to see the world upside down.


map.getViewModel().setLookAtData({
	position: {lat: 40.70808, lng: -74. 01426}, 
    zoom: 16, 
    heading: 0});
manhattan-upside

As we can see, this gives us a strange, yet familiar view. The tip of Manhattan, but on a south-up map.

Next, let's use the tilt property. Tilt represents the angle between the look-at vector and normal to the surface along z-axis, which is fancy talk for making the camera look up or down. The value goes from 0 to 90, with 0 making the camera look straight down for a standard map view. Let's keep our other properties unchanged and add a tilt of 45 degrees.


map.getViewModel().setLookAtData({
	position: {lat: 40.70808, lng: -74. 01426}, 
    zoom: 16, 
    heading: 0, 
    tilt: 45});
manhattan-tilted

As we can see, the camera is now looking up by 45 degrees in the direction of our heading. As we would expect, this means we are seeing less of Manhattan, but parts of Brooklyn and Governor's island have now come into view.

This also brings up an interesting issue. What do we do if we want to ensure that the camera shows a specific area of the map? With all this tilting and rotation, this has suddenly become a lot more complicated. Fortunately, that's what the bounds property is for. All we need to provide is an H.geo.Polygon object and setLookAtData will ensure that everything within that polygon is visible to the user.

Recently I wrote a blog post about the shapes features in the Geocoder API, which returns the outlines of areas such as countries or postal codes. Conveniently, the JavaScript API returns these areas as, you guessed it, H.geo.Polygon objects.

So, I grabbed that project, converted it to JS 3.1 and made the camera zoom into a tilted view of the selected country using the following code snippet:


lookAt = {
            bounds: cameraBounds,
            tilt: 45
         }       

map.getViewModel().setLookAtData(lookAt);
bounds

You can check out the complete project on GitHub.

(Incidentally, migrating the project to version 3.1 wasn't too much work. All I needed to do was update the modules to version 3.1, replace the credentials with the new apikey and switch to vector tiles during map initialization. You can find more details in the migration guide.)

That's it for today. Next time we'll look another exciting new feature: map customization!