Three.js text scenes on Google Maps are so-good-it-hurts 🏙🔠😎
Tags: threejs, googlemaps, opensource, webdev
Published: 2022-11-17 22:16:47

I genuinely love 3D text tracking titles in movies like the example below. We are going to put the name of the city near a historic location in a similar way for this example. Only on a map.

![Text tracking](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfg9cwc744ofwp1h7aif.gif)

Let me show you how I did something similar on google maps. Source code at the end 👇 

![3d Text on the map](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6yuh0ntytovhjl1pr36.gif)

First you need to install dependencies

```
yarn add @googlemaps/js-api-loader @googlemaps/three three

```
Import the libraries

```js
import { ThreeJSOverlayView, latLngToVector3 } from '@googlemaps/three';

import { Loader } from '@googlemaps/js-api-loader';
```
Before loading data make sure you have vector maps enabled from google console. 

![google vector maps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mugp37cn9b3w6y0qrryk.png)

```js

export const LOADER_OPTIONS = {
  apiKey: 'YOUR_API_KEY_HERE',
  version: 'beta', // to use beta features 
  libraries: [],
};

const mapOptions = {
  // location of Galata Tower at Istanbul
  center: {
    lat: 41.025615,
    lng: 28.974133,
  },
  zoom: 17,
  heading: 60,
  tilt: 50,
  mapId: 'OPTIONALLY_MAP_ID_HERE',
};

new Loader(LOADER_OPTIONS).load().then(() => {

... threejs stuff goes here 

})

```

A three.js scene inside google maps is not much different than you would see in an ordinary Three.js scene. Therefor you have light and objects. 

```js
  // installing map here
  const map = new google.maps.Map(document.getElementById('map'), mapOptions);

  // creating new scene
  const scene = new THREE.Scene();

  const ambientLight = new THREE.AmbientLight(0xffffff, 0.75);
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);

  // default light comes from above
  directionalLight.position.set(0,1,0)
  directionalLight.intensity = 1
  scene.add(directionalLight);
  scene.add(directionalLightHelper);
```
To render fonts within Three we will use `FontLoader`. I am using Helvetiker Regular font for this example. You can find it in the source code as well. 

```js
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';

  const fontLoader = new FontLoader();

  fontLoader.load('./font.json', function (font) {

   ... font stuff here

  }
```
We are going add Geometry and Material combined as a Mesh. You can't use pixel coordinates because you are rendering on a map. `latLngToVector3` is going to do the transformation for us. 

```js
    const title = 'ISTANBUL';

    const titleGeom = new TextGeometry(title, {
      font: font,
      size: 80,
      ...
    });

    const textMaterial = new THREE.MeshPhongMaterial({
      color: 0xff2d00,
      specular: 0xffffff,
    });

    const titleMesh = new THREE.Mesh(titleGeom, textMaterial);
    // set position behind the tower
    titleMesh.position.copy(
      latLngToVector3({
        lat: 41.024615,
        lng: 28.974533,
      })
    );
    
    ...
    
    scene.add(titleMesh);

```

Then we are going add the scene to the map. Here we are also enriching the experience with nice camera movement to get closer to the scene. 

```js
 // instantiate the ThreeJS Overlay with the scene and map
  const overlay = new ThreeJSOverlayView({
    scene,
    map,
    THREE,
  });
```

Animation using `requestAnimationFrame` 

```js
const animate = () => {

    ...

    if (mapOptions.tilt < 67.5) {
      mapOptions.tilt += 0.5;
      mapOptions.heading += 1;
      mapOptions.zoom += 0.005;
    } else if (mapOptions.heading <= 210) {
      mapOptions.heading += 0.4;
      mapOptions.zoom += 0.007;
    } else {
      // exit animation loop
      return;
    }

    const { tilt, heading, zoom } = mapOptions;
    map.moveCamera({ tilt, heading, zoom });

    requestAnimationFrame(animate);
  };

  requestAnimationFrame(animate);
```
Source code -> https://github.com/orabazu/threejs-text-googlemaps