Elevation along a line
Dieses Beispiel demonstriert die POST-Anfrage der Elevation-API zur Erstellung eines Höhenprofils. Durch die Integration einer Elevation-API wird jedes Segment der gezeichneten Linie verarbeitet, um Höheninformationen abzurufen. Die Höhendaten werden mit Chart.js visuell dargestellt und bieten dem Nutzer ein übersichtliches, dynamisches Diagramm, das den Höhenverlauf entlang des gezeichneten Pfads veranschaulicht.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.smartmaps.cloud/packages/smartmaps/smartmaps-gl/v2/umd/smartmaps-gl.min.js" defer></script>
<script src="/assets/src/chart.js" defer></script>
<style>
body {
margin: 0;
padding: 0;
}
html,
body,
#map {
height: 100%;
}
#controls {
position: absolute;
top: 10px;
left: 10px;
background: white;
padding: 10px;
z-index: 1;
}
#chart-container {
position: absolute;
display: none;
bottom: 40px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.23);
left: 10px;
width: 400px;
height: 200px;
background: white;
padding: 10px;
z-index: 1;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="controls">
<button id="draw-line">Draw line</button>
<button id="reset-line">Reset</button>
</div>
<div id="chart-container">
<canvas id="elevation-chart"></canvas>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const map = new smartmapsgl.Map({
apiKey: "[INSERT API-KEY]",
container: "map",
center: { lat: 46, lng: 8 },
zoom: 9,
style: smartmapsgl.MapStyle.AUTO,
terrain: {
activated: true
}
});
let drawingMode = false;
let lineCoordinates = [];
const drawLineButton = document.getElementById('draw-line');
drawLineButton.addEventListener('click', () => {
drawingMode = !drawingMode;
drawLineButton.textContent = drawingMode ? 'Calculate elevation' : 'Draw line';
if (!drawingMode) {
getElevationProfile(lineCoordinates);
document.getElementById('chart-container').style.display = 'block';
}
});
const resetLineButton = document.getElementById('reset-line');
resetLineButton.addEventListener('click', () => {
resetLine();
});
map.on('click', (e) => {
if (drawingMode) {
lineCoordinates.push([e.lngLat.lng, e.lngLat.lat]);
if (lineCoordinates.length > 1) {
map.addLayer({
id: 'line',
type: 'line',
source: {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: lineCoordinates
}
}
},
paint: {
'line-color': '#18345c',
'line-width': 3
}
});
}
}
});
function resetLine() {
if (map.getLayer('line')) {
map.removeLayer('line');
map.removeSource('line');
}
if (map.getLayer('hovered-point')) {
map.removeLayer('hovered-point');
map.removeSource('hovered-point');
}
lineCoordinates = [];
if (chart) {
chart.destroy();
}
document.getElementById('chart-container').style.display = 'none';
}
function getElevationProfile(coordinates) {
const points = [];
const distance = 300; //Distance between the points in meters
for (let i = 0; i < coordinates.length - 1; i++) {
const startPoint = coordinates[i];
const endPoint = coordinates[i + 1];
const numPoints = Math.floor(getDistance(startPoint[1], startPoint[0], endPoint[1], endPoint[0]) / distance);
for (let j = 0; j <= numPoints; j++) {
const t = j / numPoints;
const lat = startPoint[1] + t * (endPoint[1] - startPoint[1]);
const lng = startPoint[0] + t * (endPoint[0] - startPoint[0]);
points.push({ latitude: lat, longitude: lng });
}
}
const url = 'https://elevation.smartmaps.cloud/api/v2/Elevation/point?apiKey=[INSERT API-KEY]';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
points: points
})
})
.then(response => response.json())
.then(data => {
const elevations = data.features.map(feature => feature.properties.elevation);
const distances = [0];
for (let i = 1; i < points.length; i++) {
const prevPoint = points[i - 1];
const currentPoint = points[i];
const dist = getDistance(prevPoint.latitude, prevPoint.longitude, currentPoint.latitude, currentPoint.longitude);
distances.push(distances[i - 1] + dist);
}
createElevationChart(distances, elevations, points);
})
.catch(error => console.error('Error fetching elevation data:', error));
}
function getDistance(lat1, lon1, lat2, lon2) {
const R = 6371e3; // Earth's radius in meters
const φ1 = lat1 * Math.PI / 180;
const φ2 = lat2 * Math.PI / 180;
const Δφ = (lat2 - lat1) * Math.PI / 180;
const Δλ = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
let chart;
function createElevationChart(distances, elevations, points) {
const ctx = document.getElementById('elevation-chart').getContext('2d');
if (chart) {
chart.destroy();
}
chart = new Chart(ctx, {
type: 'line',
data: {
labels: distances,
datasets: [{
label: 'Height',
data: elevations,
borderColor: '#18345c',
fill: true
}]
},
options: {
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function (context) {
return 'Height ' + context.parsed.y + ' m';
}
}
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
display: false
}
},
y: {
grid: {
display: false
},
title: {
text: 'Height (m)'
}
}
},
elements: {
point: {
radius: 1,
hoverRadius: 5,
hitRadius: 5
}
},
onHover: (event, chartElement) => {
if (chartElement.length) {
const index = chartElement[0].index;
const hoveredPoint = points[index];
addMarkerToMap(hoveredPoint.latitude, hoveredPoint.longitude);
}
}
}
});
}
function addMarkerToMap(lat, lng) {
// Remove existing marker if needed
if (map.getLayer('hovered-point')) {
map.removeLayer('hovered-point');
map.removeSource('hovered-point');
}
map.addLayer({
id: 'hovered-point',
type: 'circle',
source: {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
}
},
paint: {
'circle-radius': 5,
'circle-color': '#18345c'
}
});
}
});
</script>
</body>
</html>