Query terrain elevation along a line
This example uses turf.js and queryTerrainElevation to query for elevations at regular intervals between two points. The resulting elevations are displayed in a line chart with chart.js to create a visual elevation profile.
Drag the markers to create a new elevation profile between any two points.
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Query terrain elevation along a line</title><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><link href="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css" rel="stylesheet"><script src="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"></script><style>body { margin: 0; padding: 0; }#map { position: absolute; top: 0; bottom: 0; width: 100%; }</style></head><body><style>#chart-container {height: 25%;width: 100%;position: absolute;top: 0;left: 0;right: 0;z-index: 10;background-color: rgba(255, 255, 255, 0.9);text-align: center;} #chart-inner-container {position: relative;margin: auto;height: 100%;width: 100vw;}</style> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script><script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script><div id="map"><div id="chart-container"><div id="chart-inner-container"><canvas id="chart-canvas"></canvas></div></div></div> <script> // TO MAKE THE MAP APPEAR YOU MUST // ADD YOUR ACCESS TOKEN FROM // https://account.mapbox.com mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';(async () => {const map = new mapboxgl.Map({container: 'map', // container IDstyle: 'mapbox://styles/mapbox/outdoors-v12', // style URLbounds: [-71.4, 44.36, -71.08, 44.25279]}); // default start and end point are defined as a geoJSON LineStringconst lineData = {type: 'Feature',geometry: {type: 'LineString',coordinates: [[-71.328053, 44.313497],[-71.12971, 44.25279]]},properties: {}}; map.on('style.load', () => {// add source and layer for rendering the linemap.addSource('line-data', {type: 'geojson',data: lineData}); map.addLayer({id: 'line-line-data',type: 'line',source: 'line-data',paint: {'line-width': 4,'line-color': '#37a2eb'}}); // add the digital elevation model tilesmap.addSource('mapbox-dem', {type: 'raster-dem',url: 'mapbox://mapbox.mapbox-terrain-dem-v1',tileSize: 512,maxzoom: 20});map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1 }); // add draggable markersconst marker0 = new mapboxgl.Marker({draggable: true,color: '#83f7a0'}).setLngLat(lineData.geometry.coordinates[0]).addTo(map); const marker1 = new mapboxgl.Marker({draggable: true,color: '#ed6461'}).setLngLat(lineData.geometry.coordinates[1]).addTo(map); // as the user drags a marker, update the data for the line and re-render it with setData()const updateLineData = (e, position) => {const { lng, lat } = e.target.getLngLat();lineData.geometry.coordinates[position] = [lng, lat];map.getSource('line-data').setData(lineData);}; marker0.on('drag', (e) => {updateLineData(e, 0);});marker0.on('dragend', updateElevationProfile); marker1.on('drag', (e) => {updateLineData(e, 1);});marker1.on('dragend', updateElevationProfile);}); const myLineChart = new Chart(document.getElementById('chart-canvas'), {type: 'line',data: {labels: [],datasets: []},options: {plugins: {legend: {display: false},title: {display: true,align: 'start',text: 'Elevation (m)'}},maintainAspectRatio: false,responsive: true,scales: {x: {grid: {display: false}},y: {min: 0,grid: {display: false}}},elements: {point: {radius: 0}},layout: {padding: {top: 6,right: 20,bottom: -10,left: 20}}}}); function updateElevationProfile() {// split the line into 1km segmentsconst chunks = turf.lineChunk(lineData, 1).features; // get the elevation for the leading coordinate of each segmentconst elevations = [...chunks.map((feature) => {return map.queryTerrainElevation(feature.geometry.coordinates[0]);}),// do not forget the last coordinatemap.queryTerrainElevation(chunks[chunks.length - 1].geometry.coordinates[1])]; // add dummy labelsmyLineChart.data.labels = elevations.map(() => '');myLineChart.data.datasets[0] = {data: elevations,fill: false,tension: 0.4};myLineChart.update();} // trigger the first chart draw after the DEM tiles have loadedawait map.once('idle');updateElevationProfile();})();</script> </body></html>