Skip to content
Maptoolkit Maps JS

Add 3D Terrain in Maptoolkit Maps JS

Maps JS includes a TerrainControl that adds the Maptoolkit terrain tile source and wires up the toggle button automatically. Add it to the map after the style loads. The TERRAIN constant provides the pre-configured raster-dem source pointing to the Maptoolkit terrain tile endpoint.

const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [12.805988, 47.310897],
        zoom: 12,
        pitch: 70,
        maxPitch: 85,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    map.on('load', () => {
        map.addSource('terrain-rgb', {
            type: 'raster-dem',
            tiles: [`https://tiles.maptoolkit.net/terrain/{z}/{x}/{y}.webp?api_key=${API_KEY}`],
            tileSize: 256,
            minzoom: 5,
            maxzoom: 12,
            encoding: 'terrarium'
        });

        map.setTerrain({ source: 'terrain-rgb', exaggeration: 1.0 });
    });
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Terrain Tiles - 3D Terrain - Maptoolkit Maps JS</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
    <style>
        html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
        #map { width: 100%; height: 100%; }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [12.805988, 47.310897],
        zoom: 12,
        pitch: 70,
        maxPitch: 85,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    map.on('load', () => {
        map.addSource('terrain-rgb', {
            type: 'raster-dem',
            tiles: [`https://tiles.maptoolkit.net/terrain/{z}/{x}/{y}.webp?api_key=${API_KEY}`],
            tileSize: 256,
            minzoom: 5,
            maxzoom: 12,
            encoding: 'terrarium'
        });

        map.setTerrain({ source: 'terrain-rgb', exaggeration: 1.0 });
    });
</script>
</body>
</html>

Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.

Use the Maptoolkit Connector. Create a full-page map with 3D terrain enabled by default. Center around Zell am See, zoom 12, pitch 70. Add navigation controls.

How it works

Maps JS wraps MapLibre GL JS, so the terrain setup is the same shape, with the key passed once as apiKey and reused for the style and the DEM tiles.

The source is raster-dem rather than raster, so the renderer reads each pixel as a height value instead of painting it. encoding: 'terrarium' is required: the tiles are Terrarium-encoded despite the terrain path, and the wrong encoding produces plausible but incorrect relief rather than an error.

setTerrain sits inside map.on('load') because it attaches to the loaded style.

Two camera options matter. pitch: 70 tilts far enough for relief to read, and maxPitch: 85 raises the ceiling above the default so a user can tilt further toward the horizon. exaggeration: 1.0 is true-to-life; raising it deepens valleys and sharpens peaks without changing the underlying data.

Next steps

TerrainControl gives users the toggle, which is usually the right default rather than starting tilted: terrain is the most expensive thing on the page and not every visitor wants it. exaggeration is the other dial, and above 1 it flatters the landscape rather than describing it.

From here terrain is a base for other things. A route over tilted terrain is much more legible than the same route flat, and the Routing API plus the Elevation API together give you the line and its climb profile.