Building ScrollyTelling with Free Camera API in Mapbox GL JS v2

Hiroya Kato
3 min readAug 5, 2021

--

Introduction

Build a 3D ScrollyTelling that smoothly moves the camera along the route by scrolling.

Demo page

In this article, as the title suggests, I will show an example of using Mapbox FreeCamera API.

(Read the article in Japanese

What is FreeCamera API?

This API is a new feature added to Mapbox GL JS when it was updated from v1 to v2. Using this API, you can freely manipulate the position and angle of the camera on the 3D map.

The position and angle of the camera is managed by the following instance in the FreeCameraOption object.

  • lookAtPoint
  • setPitchBearing

Please refer to the official documentation for details.

In this article, I will show an example using lookAtPoint.

Full code

The Full code can be found at the following link.

Commentary on the main points

This demo is a ScrollyTelling that integrates scrolling events with the FreeCamera API.
The FreeCamera API uses two data from routes to control the camera: one is the data of the moving route of the camera gazing point. The other is the data of the moving route of the camera itself.
First, here is an example of how to create these data.

Data 1: Moving route of camera gazing point

The data used here is the movement route of the gazing point located in the center of the camera. In other words, it is the pathway data that is the theme of ScrollyTelling.

The theme for this demo is “the route to the summit from the fifth station of Mt. Fuji”. The route I chose was the Yoshida route, which is used by more than half of the climbers.

The data was obtained from OpenStreetMap (OSM) Export.

Once the OSM data is retrieved from OSM, convert it to GeoJSON with osmtogeojson.

Extract the route you want to use from the GeoJSON you created in this way.
(Don’t forget to credit OSM when you use it)

Data 2: Moving route of the camera itself

This is the route followed by the camera itself. You can specify the parameters for the altitude separately, so you can use the same data as in Data 1.
However, for example, if a zigzag route is included the camera will swing violently along that route. That user experience can cause 3D sickness, so the data needs to be simplified.

To simplify the data, mapshaper is useful.

Code essentials

The following is an excerpt of the code that operates the FreeCamera API.

To explain briefly, the following process is repeated every time a scroll event is fired.

  1. Using Turf.js, manage scroll rate as a variable called rate.
  2. Using the rate, calculate the position according to the scroll rate from the gazing point of the camera and the movement route of the camera itself.
  3. Using each calculated position, set the FreeCamera API object (use lookAtPoint in this case)
  4. Move the camera

(For your information, scrolling events are managed by EventListener and requestAnimationFrame.)

Improvement Points

When using lookAtPoint, it is currently necessary to design the movement route of the camera itself well.
If the design fails, for example, the camera may overtake the gazing point and point in an unexpected direction. There is the problem of 3D sickness mentioned above.
For this reason, prototyping of data creation is essential in the current implementation.
I wonder if there is a good solution…

References

--

--