tileserver-gl
Version:
Map tile server for JSON GL styles - vector and server side generated raster tiles
125 lines (107 loc) • 4.28 kB
JavaScript
class ElevationInfoControl {
constructor(options) {
this.url = options["url"];
this.originalTerrain = null;
this.suppressDEMErrors = true;
this.setupErrorHandler();
}
setupErrorHandler() {
// Suppress DEM out-of-range errors that occur when placing markers at coordinates outside DEM coverage
const originalHandler = window.onerror;
window.onerror = (msg, url, line, col, error) => {
if (error && error.message && error.message.includes('out of range source coordinates for DEM data')) {
console.warn("DEM coordinate out of range (suppressed):", error);
return true; // Suppress the error
}
// Call original handler if it exists
if (typeof originalHandler === 'function') {
return originalHandler(msg, url, line, col, error);
}
};
// Also suppress promise rejections for DEM errors
const originalHandler2 = window.onunhandledrejection;
window.onunhandledrejection = (event) => {
if (event.reason && event.reason.message && event.reason.message.includes('out of range source coordinates for DEM data')) {
console.warn("DEM coordinate out of range (suppressed):", event.reason);
event.preventDefault();
return true;
}
// Call original handler if it exists
if (typeof originalHandler2 === 'function') {
return originalHandler2(event);
}
};
}
getDefaultPosition() {
const defaultPosition = "bottom-left";
return defaultPosition;
}
onAdd(map) {
this.map = map;
this.originalTerrain = map.getTerrain();
this.controlContainer = document.createElement("div");
this.controlContainer.classList.add("maplibregl-ctrl");
this.controlContainer.classList.add("maplibregl-ctrl-group");
this.controlContainer.classList.add("maplibre-ctrl-elevation");
this.controlContainer.textContent = "Elevation: Click on Map";
this.marker = new maplibregl.Marker();
map.on('click', (e) => {
if (!map.transform.isPointOnMapSurface(e.point)) {
this.controlContainer.textContent = "Elevation: Click on Globe";
return;
}
var url = this.url;
var lngLat = e.lngLat;
// Validate coordinates are within valid range
if (typeof lngLat !== 'object' || typeof lngLat.lng !== 'number' || typeof lngLat.lat !== 'number') {
this.controlContainer.textContent = "Elevation: Invalid coordinates";
return;
}
var coord = {"z": Math.floor(map.getZoom()), "x": lngLat.lng.toFixed(7), "y": lngLat.lat.toFixed(7)};
for(var key in coord) {
url = url.replace(new RegExp('{'+ key +'}','g'), coord[key]);
}
try {
if (this.marker) {
this.marker.remove();
}
this.marker = new maplibregl.Marker();
this.marker.setLngLat({lng: lngLat.lng, lat: lngLat.lat});
this.marker.addTo(this.map);
} catch (_err) {
// If placement fails, continue without marker
console.error("Marker placement error:", _err);
}
let request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = () => {
if (request.status !== 200) {
this.controlContainer.textContent = "Elevation: No value";
} else {
this.controlContainer.textContent = `Elevation: ${JSON.parse(request.responseText).elevation} (${JSON.stringify(coord)})`;
}
};
request.send();
});
return this.controlContainer;
}
onRemove() {
if (
!this.controlContainer ||
!this.controlContainer.parentNode ||
!this.map
) {
return;
}
this.controlContainer.parentNode.removeChild(this.controlContainer);
// Restore terrain if it was originally enabled
if (this.originalTerrain && !this.map.getTerrain()) {
this.map.setTerrain(this.originalTerrain);
}
if (this.marker) {
this.marker.remove();
this.marker = undefined;
}
this.map = undefined;
}
};