Level of detail control
Adjust how many distinct zoom levels are visible on screen and manage the tile density budget at high pitch angles.
This example demonstrates how to use the setSourceTileLodParams() method to optimize map tile loading and rendering performance when the camera is heavily tilted (high pitch), displaying tile boundaries to visualize the Level of Detail (LOD) transitions.
NPM module setup
npm install --save @maptiler/sdk
import { Map, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = new Map({
container: 'map',
zoom: 12,
pitch: 77,
center: [0, 0],
style: {
version: 8,
sources: {
numbers: {
type: 'raster',
url: 'https://demotiles.maplibre.org/debug-tiles/number/tiles.json',
tileSize: 256,
maxzoom: 19
}
},
layers: [
{
id: 'numbers',
type: 'raster',
source: 'numbers'
}
]
},
maxZoom: 22,
maxPitch: 85
});
function setLodParamsFromUi() {
const maxZoomVal = document.getElementById('max-zoom-levels-slider').value;
const tileCountVal = document.getElementById('tile-count-ratio-slider').value;
// Update UI labels
document.getElementById('max-zoom-levels-value').textContent = maxZoomVal;
document.getElementById('tile-count-ratio-value').textContent = tileCountVal;
// Apply parameters to our debug tiles source 'numbers'
try {
map.setSourceTileLodParams(maxZoomVal, tileCountVal);
} catch (e) {
console.warn("setSourceTileLodParams failed for source 'numbers':", e);
}
}
map.on('load', () => {
document.getElementById('max-zoom-levels-slider').addEventListener('input', setLodParamsFromUi);
document.getElementById('tile-count-ratio-slider').addEventListener('input', setLodParamsFromUi);
// Initial parameters setup
setLodParamsFromUi();
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="robots" content="noindex" />
<title>Level of Detail Control</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="map"></div>
<div class="control-panel">
<h3>LOD Parameters</h3>
<div class="control-row">
<div class="control-label-wrapper">
<label class="control-label" for="max-zoom-levels-slider"
>Max Zoom Levels On Screen</label
>
<span id="max-zoom-levels-value" class="control-value">9.0</span>
</div>
<input type="range" id="max-zoom-levels-slider" min="1" max="11" step="1.0" value="9.0" />
</div>
<div class="control-row">
<div class="control-label-wrapper">
<label class="control-label" for="tile-count-ratio-slider"
>Tile Count Max/Min Ratio</label
>
<span id="tile-count-ratio-value" class="control-value">3.0</span>
</div>
<input type="range" id="tile-count-ratio-slider" min="1" max="10" step="0.1" value="3.0" />
</div>
</div>
<script type="module" src="./main.js"></script>
</body>
</html>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
.control-panel {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
position: absolute;
top: 15px;
left: 15px;
color: #333;
background: rgba(255, 255, 255, 0.95);
padding: 15px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 10;
width: 280px;
max-width: calc(100% - 30px);
}
.control-panel h3 {
margin: 0 0 12px 0;
font-size: 14px;
font-weight: 600;
color: #111;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
.control-row {
display: flex;
flex-direction: column;
margin-bottom: 12px;
}
.control-row:last-child {
margin-bottom: 0;
}
.control-label-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4px;
}
.control-label {
font-size: 11px;
font-weight: 500;
color: #555;
}
.control-value {
font-size: 11px;
font-weight: bold;
color: #000;
}
.control-row input[type="range"] {
width: 100%;
margin: 4px 0;
}
Learn more
How it works
When the map is pitched and the horizon is visible, tiles in the distance appear smaller and closer to the horizon. By default, the rendering engine balances performance and quality by loading fewer, lower-resolution tiles in the distance.
With setSourceTileLodParams(), you can override this behavior:
- Max Zoom Levels On Screen (
maxZoomLevelsOnScreen): Limits the variety of distinct zoom levels rendered simultaneously. Lowering this value reduces the “depth” of zoom levels rendered, which can save network requests and memory, but distant areas will look less detailed. - Tile Count Max/Min Ratio (
tileCountMaxMinRatio): Controls the budget of tiles. A higher ratio allows more tiles to be loaded across different zoom levels, while a lower ratio restricts them, forcing distant tiles to stay at a lower zoom level to save resources.