Animation with 3D Module

This example demonstrates how to use the MaptilerAnimation class in combination with the @maptiler/3d module. It features a UFO model orbiting the Burj Khalifa, with controls to pause, play, adjust the playback rate, and advance frame by frame. The animation linearly interpolates the position (longitude, latitude, and altitude) of the UFO based on a set of defined keyframes.

NPM module setup


npm install --save @maptiler/sdk @maptiler/3d
import { Map, MapStyle, config, MaptilerAnimation } from "@maptiler/sdk";
import { Layer3D } from "@maptiler/3d";
import "@maptiler/sdk/dist/maptiler-sdk.css";

config.apiKey = "ivHgEpo8G3yNUmHYHp61";
const map = new Map({
  container: "map",
  style: MapStyle.STREETS.DARK,
  hash: false,
  geolocateControl: false,
  navigationControl: false,
  terrain: true,
  bearing: -30,
  maxPitch: 60,
  minPitch: 60,
  pitch: 60,
  zoom: 15.3,
  maxZoom: 15.3,
  minZoom: 15.3,
  center: [55.273056, 25.199267],
});

function getElementsByIds(ids) {
  return ids.map((id) => document.getElementById(id));
}

map.on("load", async function () {
  const animation = new MaptilerAnimation({
    keyframes: getKeyframes(),
    duration: 2500,
    iterations: Infinity,
  });

  const layer3D = new Layer3D("3d-scene");
  map.addLayer(layer3D);

  await layer3D.addMeshFromURL(
    "khalifa",
    "https://docs-media.maptiler.com/docs/models/burj_khalifa/scene.gltf",
    {
      lngLat: [55.2743164, 25.1973882],
      heading: -2,
      scale: 0.013,
    },
  );

  await layer3D.addMeshFromURL(
    "ufo",
    "https://docs-media.maptiler.com/docs/models/ufo/scene.gltf",
    {
      lngLat: [55.273, 25.197],
      altitude: 500,
      scale: 10,
    },
  );

  animation.addEventListener("timeupdate", (e) => {
    map.setBearing(map.getBearing() + 0.1);
    const ufo = layer3D.getItem3D("ufo");
    if (ufo) {
      ufo.modify({
        lngLat: [e.props.lng, e.props.lat],
        altitude: e.props.altitude,
      });
    }
  });

  animation.addEventListener("playbackratechange", (e) => {
    const playbackRateElement = document.getElementById("playbackRate");
    if (!playbackRateElement) return;
    playbackRateElement.innerText = e.playbackRate.toFixed(1) + "x";
  });

  const [playButton, pauseButton, fasterButton, slowerButton, frameAdvanceButton] =
    getElementsByIds(["play", "pause", "faster", "slower", "frame-advance"]);

  playButton?.addEventListener("click", () => {
    animation.play();
  });

  pauseButton?.addEventListener("click", () => {
    animation.pause();
  });

  fasterButton?.addEventListener("click", () => {
    const currentSpeed = animation.getPlaybackRate();
    animation.setPlaybackRate(currentSpeed + 0.2);
  });

  slowerButton?.addEventListener("click", () => {
    const currentSpeed = animation.getPlaybackRate();
    animation.setPlaybackRate(currentSpeed - 0.2);
  });

  frameAdvanceButton?.addEventListener("click", () => {
    animation.setCurrentDelta(animation.getCurrentDelta() + 0.01);
  });

  animation.play();
});

function getKeyframes() {
  return [
    {
      delta: 0,
      easing: "ElasticInOut",
      props: {
        lng: 55.273,
        lat: 25.197,
        altitude: 300,
      },
    },
    {
      delta: 0.33333,
      easing: "ElasticInOut",
      props: {
        lng: 55.27439873444448,
        lat: 25.198719685352263,
        altitude: 250,
      },
    },
    {
      delta: 0.666666,
      easing: "ElasticInOut",
      props: {
        lng: 55.2753633312754,
        lat: 25.195489657613702,
        altitude: 350,
      },
    },
    {
      delta: 1.0,
      easing: "ElasticInOut",
      props: {
        lng: 55.273,
        lat: 25.197,
        altitude: 300,
      },
    },
  ];
}
Animations and Animated Routes

Animations and Animated Routes

Examples

Animates a path or route on the map based on keyframes or GeoJSON data.

Animate a point along a route

Animate a point along a route

Examples

Smoothly animate a point along a route using Turf.

Customize camera animations

Customize camera animations

Examples

Customize map camera animations using the AnimationOptions property.

Animate routes with a dynamic camera

Animate routes dynamic camera

Examples

Animate multidimensional routes with a dynamic camera that follows the journey in real-time.

Was this helpful?