Skip to main content


In the Three.js custom renderer guide we rendered a static cube using Three.js. What if we want to rotate or move things around inside MapillaryJS? Well, we can do that too, we just have to add a few lines of code to our cube renderer.

You will learn
  • How to animate objects in MapillaryJS
  • How to trigger rerender to ensure that the animation continues

Creating the Animation Renderer#

We will add functionality to the cube renderer from the Three.js Renderer guide so make sure that you have to study that before jumping into this example. Here we will just go through the new functionality that we will add.

Specifying the Rotation Speed#

We want to be able to change the rotation speed of our cube, so we add a rotationSpeed property.

const cube = {  // ...  rotationSpeed: 1,};

Keeping the Time#

We will add a Three.js Clock member to our renderer. The clock will be readonly so we assign it in the constructor.

class RotatingCubeRenderer {  constructor(cube) {    // ...    this.clock = new Clock();  }}

Storing a Viewer Reference#

We will make use of the viewer in the render method so we store a reference to it through the viewer parameter of onAdd.

class RotatingCubeRenderer {  // ...  onAdd(viewer, reference, context) {    this.viewer = viewer;    // ...  }}

Trigger Rerender#

Our onReference and onRemove implementations remain the same, so let's move on to the render method. Here we make use of the clock to rotate the cube mesh according to our rotation speed and the elapsed time between each animation frame.

Finally, we call the Viewer.triggerRerender method to force the Viewer to rerender and call our render implementation on every animation frame. We need to trigger rerender on every animation frame because we want our cube to rotate indefinitely.

class RotatingCubeRenderer {  // ...  render(context, viewMatrix, projectionMatrix) {    const {camera, clock, scene, cube, renderer, viewer} = this;
    const delta = clock.getDelta();    const {rotationSpeed} = cube;    cube.mesh.rotateZ(rotationSpeed * delta);    cube.mesh.rotateY(0.7 * rotationSpeed * delta);
    // ...
    viewer.triggerRerender();  }}

Rerendering on every frame has a performance impact. Whenever it is possible, for example if your animation has completed, it is advices to avoid triggering rerender.

Adding the Renderer#

Now that we have implemented our rotating cube renderer, we just need to add it to the Viewer through the Viewer.addCustomRenderer method.


Try changing the cube's rotation speed.

Live Editor
SyntaxError: Unexpected token (1:8)
1 : return ()


  • To animate objects in MapillaryJS, use the elapsed time when applying object transforms
  • Trigger rerender to ensure that the animation continues
  • Avoid triggering rerender if your animation has completed to optimize resource usage

You can view the complete code in the Animation example.