3D Building
Buildings: 0
Status: Loading...
html
<!DOCTYPE html>
<html>
<head>
<title>3D Buildings</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<h3>3D Buildings</h3>
<div class="info">
<div>Buildings: <span id="buildingCount">0</span></div>
<div>Status: <span id="status">Loading...</span></div>
</div>
<script>
const token='YOUR_TOKEN';
// Initialize map with the MapMetrics Atlas style
const map = new mapmetricsgl.Map({
container: 'map',
style: `https://gateway.mapmetrics-atlas.net/styles/?fileName=dd508822-9502-4ab5-bfe2-5e6ed5809c2d/portal.json&token=${token}`,
center: [5.47, 51.49], // Center of your building data
zoom: 16,
pitch: 60,
bearing: -30
});
map.on('load', () => {
console.log('Map loaded');
document.getElementById('status').textContent = 'Map loaded';
// Add the 3D buildings source
map.addSource('buildings', {
type: 'vector',
tiles: ['https://building.mapmetrics-atlas.net/data/buildings/{z}/{x}/{y}.pbf'],
minzoom: 13,
maxzoom: 16
});
// Add 3D buildings layer
map.addLayer({
id: 'buildings-3d',
type: 'fill-extrusion',
source: 'buildings',
'source-layer': 'building',
paint: {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': [
'case',
['has', 'height'],
['get', 'height'],
['has', 'estimated_height'],
['get', 'estimated_height'],
['has', 'building:levels'],
['*', ['to-number', ['get', 'building:levels']], 3],
['has', 'floors'],
['*', ['to-number', ['get', 'floors']], 3],
10
],
'fill-extrusion-base': 0,
'fill-extrusion-opacity': 0.9
}
});
updateBuildingCount();
});
function updateBuildingCount() {
const features = map.queryRenderedFeatures({ layers: ['buildings-3d'] });
document.getElementById('buildingCount').textContent = features.length;
}
// Update on map movement
map.on('moveend', () => {
updateBuildingCount();
});
// Add popup on click for building info
map.on('click', 'buildings-3d', (e) => {
const coordinates = e.lngLat;
const properties = e.features[0].properties;
const actualHeight = properties.height || properties.estimated_height ||
(properties['building:levels'] ? parseInt(properties['building:levels']) * 3 : null) ||
(properties.floors ? parseInt(properties.floors) * 3 : null) || 10;
const popupContent = `
<strong style="color:black;">Building Info:</strong><br>
Height: ${actualHeight}m<br>
Levels: ${properties['building:levels'] || 'N/A'}<br>
Type: ${properties['building'] || properties['building:type'] || 'N/A'}<br>
Name: ${properties.name || 'N/A'}
`;
new mapmetricsgl.Popup()
.setLngLat(coordinates) // place popup at clicked point
.setHTML(popupContent) // set the content
.addTo(map); // add popup to the map
});
// Change cursor on hover
map.on('mouseenter', 'buildings-3d', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'buildings-3d', () => {
map.getCanvas().style.cursor = '';
});
</script>
</body>
</html>