Add Contour Lines

Use the maplibre-contour plugin to render elevation contour lines on a map from a raster-dem source.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add Contour Lines</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/trackasia-gl@1.0.5/dist/trackasia-gl.js"></script>
<link href="https://unpkg.com/trackasia-gl@1.0.5/dist/trackasia-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/maplibre-contour@0.0.2/dist/index.min.js"></script>
<script>
var demSource = new mlcontour.DemSource({
url: 'https://static.track-asia.com/demotiles/terrain-tiles/{z}/{x}/{y}.png?key=public_key',
encoding: 'mapbox',
maxzoom: 12,
// offload contour line computation to a web worker
worker: true
});
// calls trackasiagl.addProtocol to register a dynamic vector tile provider that
// downloads raster-dem tiles, computes contour lines, and encodes as a vector
// tile for each tile request from maplibre
demSource.setupMaplibre(trackasiagl);
var map = (window.map = new trackasiagl.Map({
container: 'map',
zoom: 13,
center: [11.3229, 47.2738],
hash: true,
style: {
version: 8,
glyphs: 'https://static.track-asia.com/demotiles/font/{fontstack}/{range}.pbf?key=public_key',
sources: {
hillshadeSource: {
type: 'raster-dem',
// share cached raster-dem tiles with the contour source
tiles: [demSource.sharedDemProtocolUrl],
tileSize: 512,
maxzoom: 12
},
contourSourceFeet: {
type: 'vector',
tiles: [
demSource.contourProtocolUrl({
// meters to feet
multiplier: 3.28084,
overzoom: 1,
thresholds: {
// zoom: [minor, major]
11: [200, 1000],
12: [100, 500],
13: [100, 500],
14: [50, 200],
15: [20, 100]
},
elevationKey: 'ele',
levelKey: 'level',
contourLayer: 'contours'
})
],
maxzoom: 15
}
},
layers: [
{
id: 'hills',
type: 'hillshade',
source: 'hillshadeSource',
layout: { visibility: 'visible' },
paint: { 'hillshade-exaggeration': 0.25 }
},
{
id: 'contours',
type: 'line',
source: 'contourSourceFeet',
'source-layer': 'contours',
paint: {
'line-opacity': 0.5,
// "major" contours have level=1, "minor" have level=0
'line-width': ['match', ['get', 'level'], 1, 1, 0.5]
}
},
{
id: 'contour-text',
type: 'symbol',
source: 'contourSourceFeet',
'source-layer': 'contours',
filter: ['>', ['get', 'level'], 0],
paint: {
'text-halo-color': 'white',
'text-halo-width': 1
},
layout: {
'symbol-placement': 'line',
'text-size': 10,
'text-field': [
'concat',
['number-format', ['get', 'ele'], {}],
"'"
],
'text-font': ['Noto Sans Bold']
}
}
]
}
}));
</script>
</body>
</html>