---
title: "Add a airplane 3D model | 3D JS | JavaScript maps SDK"
description: "Add and position flying 3D airplane models on maps."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# Add a airplane 3D model

Use the [MapTiler 3D JS module](https://docs.maptiler.com/sdk-js/modules/3d/) to add a airplane model to the map. Thanks to the 3D JS module we can add 3D models to the map (flying) at the height above sea level that we want.

This demonstration showcases a compact control interface that allows us to modify various model parameters and observe their immediate impact on the model’s behavior.

[Model credit](#fn:1)

### NPM module setup

```bash
npm install --save @maptiler/sdk @maptiler/3d lil-gui
```

#### main.js

```js
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { Layer3D, AltitudeReference } from '@maptiler/3d';
import { GUI } from 'lil-gui';

config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';

const map = new Map({
  container: document.getElementById('map'),
  hash: true,
  style: MapStyle.OUTDOOR.DARK,
  zoom: 11,
  center: [7.22, 46.18],
  pitch: 60,
  maxPitch: 85,
  terrainControl: true,
  terrain: true,
  maptilerLogo: true,
});

(async () => {
  await map.onReadyAsync();

  map.setSky({
    "sky-color": "#0C2E4B",
    "horizon-color": "#09112F",
    "fog-color": "#09112F",
    "fog-ground-blend": 0.5,
    "horizon-fog-blend": 0.1,
    "sky-horizon-blend": 1.0,
    "atmosphere-blend": 0.5,
  })

  const layer3D = new Layer3D("custom-3D-layer");
  map.addLayer(layer3D);

  // Increasing the intensity of the ambient light 
  layer3D.setAmbientLight({intensity: 2});

  // Adding a point light
  layer3D.addPointLight("point-light", {intensity: 30});

  const gui = new GUI({ width: 200 });

  // Adding a mesh of a plane.

  const guiObj = {
    heading: 0,
    scale: 1,
    altitude: 3000,
    opacity: 1,
    wireframe: false,
    altitudeReference: "MEAN_SEA_LEVEL",
    removePlane: () => {
      layer3D.removeMesh(originalPlaneID);
    }
  }

  const originalPlaneID = "plane";
  const mesh = await layer3D.addMeshFromURL(
    originalPlaneID,
    "https://docs-media.maptiler.com/docs/models/plane_a340.glb",
    {
      scale: guiObj.scale,
      altitude: guiObj.altitude,
      altitudeReference: AltitudeReference.MEAN_SEA_LEVEL,
      wireframe: guiObj.wireframe,
      lngLat: [7.22, 46.18]
    }
  );

  let planeCanMove = false;

  // Adding mesh of a plane
  map.on("mousemove", (e) => {
    if (!planeCanMove) return;
    mesh.modify({lngLat: e.lngLat})
  });

  map.on("click", (e) => {
    planeCanMove = !planeCanMove;
  });

  gui.add( guiObj, 'heading', 0, 360, 0.1 )
  .onChange((heading) => {
    mesh.modify({heading});
  });

  gui.add( guiObj, 'scale', 0.01, 5, 0.01 )
  .onChange((scale) => {
    mesh.modify({scale});
  });

  gui.add( guiObj, 'altitude', 0, 10000, 1 )
  .onChange((altitude) => {
    mesh.modify({altitude});
  });

  gui.add( guiObj, 'opacity', 0, 1)
  .onChange((opacity) => {
    mesh.modify({opacity});
  });

  gui.add( guiObj, 'altitudeReference', ["MEAN_SEA_LEVEL", "GROUND"])
  .onChange((altRef) => {
    mesh.modify({altitudeReference: maptiler3d.AltitudeReference[altRef]});
  });

  gui.add( guiObj, "wireframe" )
  .onChange((wireframe) => {
    mesh.modify({wireframe});
  });

  gui.add( guiObj, "removePlane" );

})()
```

#### index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="robots" content="noindex">
  <title>Add a airplane 3D model | NPM example</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>
  <div id="map"></div>
  <div id="info">
  <p>
    Click on the map to move the plane. You can then click again to fix its position.
  </p>
  </div>
  <script type="module" src="./main.js"></script>
</body>
</html>
```

#### style.css

```css
body {margin: 0; padding: 0;}
#map {position: absolute; top: 0; bottom: 0; width: 100%;}
.lil-gui.autoPlace {
  right: inherit;
  left: 15px;
}
#info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  width: fit-content;
  height: fit-content;
  text-align: center;
  padding: 15px;
  color: white;
  background-color: #0009;
  border-radius: 5px;
  font-family: monospace;
  margin: auto;
  margin-bottom: 25px;
  z-index: 2;
  backdrop-filter: blur(10px);
}
```

### Basic JavaScript setup

```html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add a 3D model</title>
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.19"></script>
<script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
<link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
<!-- Importing MapTiler 3D js -->
<script src="https://cdn.maptiler.com/maptiler-3d/v4.0.1/maptiler-3d.umd.min.js"></script>
<style>
  body {margin: 0; padding: 0;}
  #map {position: absolute; top: 0; bottom: 0; width: 100%;}
  .lil-gui.autoPlace {
    right: inherit;
    left: 15px;
  }
  #info {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    width: fit-content;
    height: fit-content;
    text-align: center;
    padding: 15px;
    color: white;
    background-color: #0009;
    border-radius: 5px;
    font-family: monospace;
    margin: auto;
    margin-bottom: 25px;
    z-index: 2;
    backdrop-filter: blur(10px);
  }
</style>
</head>
<body>
<div id="map"></div>
<div id="info">
  <p>
    Click on the map to move the plane. You can then click again to fix its position.
  </p>
</div>
<script>
  maptilersdk.config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';

  const map = new maptilersdk.Map({
    container: document.getElementById('map'),
    hash: true,
    style: maptilersdk.MapStyle.OUTDOOR.DARK,
    zoom: 11,
    center: [7.22, 46.18],
    pitch: 60,
    maxPitch: 85,
    terrainControl: true,
    terrain: true,
    maptilerLogo: true,
  });

  (async () => {
    await map.onReadyAsync();

    map.setSky({
      "sky-color": "#0C2E4B",
      "horizon-color": "#09112F",
      "fog-color": "#09112F",
      "fog-ground-blend": 0.5,
      "horizon-fog-blend": 0.1,
      "sky-horizon-blend": 1.0,
      "atmosphere-blend": 0.5,
    })

    const layer3D = new maptiler3d.Layer3D("custom-3D-layer");
    map.addLayer(layer3D);

    // Increasing the intensity of the ambient light 
    layer3D.setAmbientLight({intensity: 2});

    // Adding a point light
    layer3D.addPointLight("point-light", {intensity: 30});

    const gui = new lil.GUI({ width: 200 });

    // Adding a mesh of a plane.

    const guiObj = {
      heading: 0,
      scale: 1,
      altitude: 3000,
      opacity: 1,
      wireframe: false,
      altitudeReference: "MEAN_SEA_LEVEL",
      removePlane: () => {
        layer3D.removeMesh(originalPlaneID);
      }
    }
  
    const originalPlaneID = "plane";
    const mesh = await layer3D.addMeshFromURL(
      originalPlaneID,
      "https://docs-media.maptiler.com/docs/models/plane_a340.glb",
      {
        scale: guiObj.scale,
        altitude: guiObj.altitude,
        altitudeReference: maptiler3d.AltitudeReference.MEAN_SEA_LEVEL,
        wireframe: guiObj.wireframe,
        lngLat: [7.22, 46.18]
      }
    );

    let planeCanMove = false;

    // Adding mesh of a plane
    map.on("mousemove", (e) => {
      if (!planeCanMove) return;
      mesh.modify({lngLat: e.lngLat})
    });

    map.on("click", (e) => {
      planeCanMove = !planeCanMove;
    });

    gui.add( guiObj, 'heading', 0, 360, 0.1 )
    .onChange((heading) => {
      mesh.modify({heading});
    });

    gui.add( guiObj, 'scale', 0.01, 5, 0.01 )
    .onChange((scale) => {
      mesh.modify({scale});
    });

    gui.add( guiObj, 'altitude', 0, 10000, 1 )
    .onChange((altitude) => {
      mesh.modify({altitude});
    });

    gui.add( guiObj, 'opacity', 0, 1)
    .onChange((opacity) => {
      mesh.modify({opacity});
    });

    gui.add( guiObj, 'altitudeReference', ["MEAN_SEA_LEVEL", "GROUND"])
    .onChange((altRef) => {
      mesh.modify({altitudeReference: maptiler3d.AltitudeReference[altRef]});
    });

    gui.add( guiObj, "wireframe" )
    .onChange((wireframe) => {
      mesh.modify({wireframe});
    });

    gui.add( guiObj, "removePlane" );

  })()
    
</script>
</body>
</html>
```

[plane a340](https://skfb.ly/oJWGw) by mamont nikita is licensed under [Creative Commons Attribution](https://creativecommons.org/licenses/by/4.0/) [↩](#fnref:1)

## Related examples

### [Add multiple 3D models](https://docs.maptiler.com/sdk-js/examples/3d-js-multi/)

Examples

Incorporate multiple 3D models with adjustable parameters on maps.

### [Animate a 3D plane flight](https://docs.maptiler.com/sdk-js/examples/3d-js-flight/)

Examples

Simulate and animate a 3D plane flight between cities.

### [Start with AR maps](https://docs.maptiler.com/sdk-js/examples/ar-control/)

Examples

Add an AR control button to map 3D viewports.

### [3D terrain map](https://docs.maptiler.com/sdk-js/examples/3d-map/)

Tutorials

Create and display 3D terrain maps on web pages.
