Skip to content

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>