Three.js text scenes on Google Maps are so-good-it-hurts ππ π
Orhun Γzer
Posted on November 17, 2022
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.
Let me show you how I did something similar on google maps. Source code at the end π
First you need to install dependencies
yarn add @googlemaps/js-api-loader @googlemaps/three three
Import the libraries
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.
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.
// 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.
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.
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.
// instantiate the ThreeJS Overlay with the scene and map
const overlay = new ThreeJSOverlayView({
scene,
map,
THREE,
});
Animation using requestAnimationFrame
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
Posted on November 17, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.