본문 바로가기
API사용

[Mapbox] 맵 박스 3D 건물 세우기 예제

by 미눅스[멘토] 2025. 3. 13.
728x90

1.style = "mapbox://styles/mapbox/standard" 를 사용할 경우

 

3D 건물 핵심코드

    const map = new mapboxgl.Map({
        container: 'map', // container ID
        style: 'mapbox://styles/mapbox/standard', //mapbox://styles/mapbox/standard //mapbox://styles/mapbox/streets-v12
        center: [126.735901, 37.348980], // 한국
        zoom: 9, // starting zoom
        pitch: 45,// 3D 시점으로 기울기 적용
        bearing: -17.6,//지도 회전 각도
        container: 'map',// 지도를 렌더링할 HTML 요소의 ID
        antialias: true, //부드러운 렌더링을 위한 안티앨리어싱 활성화 (3D 그래픽 품질 향상)
        projection: 'albers'
    });

style: 'mapbox://styles/mapbox/standard' 이 3D의 핵심이다

 projection 옵션이 핵심요서 설정이다.

 

antialias 의 옵션 값 설명
'globe' 🌍 3D 지구 투영 (기본 설정)
'mercator' 🗺️ 일반 평면 지도 (기본 2D 방식)
'albers' 📐 면적 보존형 투영 (주로 통계 데이터용)
'equalEarth' 🌎 면적 보존형 투영 (Equal Earth)
'equirectangular' 🏛️ 균등 직각 투영 (기본적인 지도 형태)
'lambertConformalConic' 🏔️ 램버트 정규 원뿔 투영 (기상 및 항공 지도용)
'naturalEarth' 🌍 네추럴 어스 투영 (면적 보존)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mapbox GL JS map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
    mapboxgl.accessToken = 'minwooToken';
    const map = new mapboxgl.Map({
        container: 'map', // container ID
        style: 'mapbox://styles/mapbox/standard', //mapbox://styles/mapbox/standard //mapbox://styles/mapbox/streets-v12
        center: [126.735901, 37.348980], // 한국
        zoom: 9, // starting zoom
        pitch: 45,// 3D 시점으로 기울기 적용
        bearing: -17.6,//지도 회전 각도
        container: 'map',// 지도를 렌더링할 HTML 요소의 ID
        antialias: true, //부드러운 렌더링을 위한 안티앨리어싱 활성화 (3D 그래픽 품질 향상)
        projection: 'albers'
    });

</script>

</body>
</html>

한국 멀리서 봤을때

 

확대하면 건물들이 3D형태로 나와있다.

 

 

 

 

2.style = "mapbox://styles/mapbox/standard" 를 사용하지 않을경우

style = "mapbox://styles/mapbox/standard를 사용하지 않을경우 3D 건물을 지원하지 않는다.

그래서 따로 3D rayer를 추가해 주면 된다.

3D 건물추가 핵심코드

    map.on('style.load', () => {
        // Insert the layer beneath any symbol layer.
        const layers = map.getStyle().layers;
        const labelLayerId = layers.find(
            (layer) => layer.type === 'symbol' && layer.layout['text-field']
        ).id;

        // 맵박스 스트리트의 '빌딩' 레이어
        // 벡터 타일셋에는 건물 높이 데이터가 포함되어 있다.
        // OpenStreetMap에서.
        map.addLayer(
            {
                'id': 'add-3d-buildings', // 레이어 ID (3D 건물을 추가하는 레이어)
                'source': 'composite', // 데이터 소스 (Mapbox의 기본 'composite' 소스 사용)
                'source-layer': 'building', // 건물 데이터가 포함된 소스 레이어 이름
                'filter': ['==', 'extrude', 'true'], // 'extrude' 속성이 'true'인 건물만 선택 (3D 건물만 표시)
                'type': 'fill-extrusion', // 3D 건물을 표현하는 타입 (입체적인 채우기)
                'minzoom': 15, // 줌 레벨이 15 이상일 때만 보이도록 설정

                'paint': {
                    'fill-extrusion-color': '#aaa', // 건물 색상 (회색 계열)

                    // 'interpolate' 표현식을 사용하여 사용자가 줌 인/아웃할 때
                    // 건물이 부드럽게 높아지거나 낮아지도록 설정
                    'fill-extrusion-height': [
                        'interpolate', // 값이 변할 때 부드럽게 보이도록 보간(interpolation) 처리
                        ['linear'], // 선형(linear) 보간 방식 사용 (부드럽게 변함
                        ['zoom'], // 줌 레벨에 따라 값을 조정
                        15, 0, // 줌 레벨 15에서는 건물 높이를 0으로 설정 (평면으로 보임)
                        15.05, ['get', 'height'] // 줌 레벨 15.05 이상에서는 데이터에서 'height' 속성 값을 가져와 적용
                    ],

                    'fill-extrusion-base': [
                        'interpolate', // 건물의 최소 높이(base)를 부드럽게 적용
                        ['linear'], // 선형 보간 방식 사용 (부드럽게 변함
                        ['zoom'], // 줌 레벨에 따라 조정
                        15, 0, // 줌 레벨 15에서는 건물의 바닥(base)을 0으로 설정
                        15.05, ['get', 'min_height'] // 줌 레벨 15.05 이상에서는 'min_height' 속성 값을 적용
                    ],

                    'fill-extrusion-opacity': 0.6 // 건물의 투명도 (0.6, 반투명)
                }
            },
            labelLayerId
        );
    });

 

전체코드

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mapbox GL JS map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
    mapboxgl.accessToken = 'minwooToken';
    const map = new mapboxgl.Map({
        container: 'map', // 지도를 렌더링할 HTML 요소의 ID
        style: 'mapbox://styles/mapbox/streets-v12',
        center: [126.735901, 37.348980], // 한국
        zoom: 9, // starting zoom
       pitch: 45,// 3D 시점으로 기울기 적용
        bearing: -17.6,//지도 회전 각도
        antialias: true//부드러운 렌더링을 위한 안티앨리어싱 활성화 (3D 그래픽 품질 향상)
    });

 
    // 3D 건물 추가
    map.on('style.load', () => {
        // Insert the layer beneath any symbol layer.
        const layers = map.getStyle().layers;
        const labelLayerId = layers.find(
            (layer) => layer.type === 'symbol' && layer.layout['text-field']
        ).id;

        // 맵박스 스트리트의 '빌딩' 레이어
        // 벡터 타일셋에는 건물 높이 데이터가 포함되어 있다.
        // OpenStreetMap에서.
        map.addLayer(
            {
                'id': 'add-3d-buildings', // 레이어 ID (3D 건물을 추가하는 레이어)
                'source': 'composite', // 데이터 소스 (Mapbox의 기본 'composite' 소스 사용)
                'source-layer': 'building', // 건물 데이터가 포함된 소스 레이어 이름
                'filter': ['==', 'extrude', 'true'], // 'extrude' 속성이 'true'인 건물만 선택 (3D 건물만 표시)
                'type': 'fill-extrusion', // 3D 건물을 표현하는 타입 (입체적인 채우기)
                'minzoom': 15, // 줌 레벨이 15 이상일 때만 보이도록 설정

                'paint': {
                    'fill-extrusion-color': '#aaa', // 건물 색상 (회색 계열)

                    // 'interpolate' 표현식을 사용하여 사용자가 줌 인/아웃할 때
                    // 건물이 부드럽게 높아지거나 낮아지도록 설정
                    'fill-extrusion-height': [
                        'interpolate', // 값이 변할 때 부드럽게 보이도록 보간(interpolation) 처리
                        ['linear'], // 선형(linear) 보간 방식 사용 (부드럽게 변함
                        ['zoom'], // 줌 레벨에 따라 값을 조정
                        15, 0, // 줌 레벨 15에서는 건물 높이를 0으로 설정 (평면으로 보임)
                        15.05, ['get', 'height'] // 줌 레벨 15.05 이상에서는 데이터에서 'height' 속성 값을 가져와 적용
                    ],

                    'fill-extrusion-base': [
                        'interpolate', // 건물의 최소 높이(base)를 부드럽게 적용
                        ['linear'], // 선형 보간 방식 사용 (부드럽게 변함
                        ['zoom'], // 줌 레벨에 따라 조정
                        15, 0, // 줌 레벨 15에서는 건물의 바닥(base)을 0으로 설정
                        15.05, ['get', 'min_height'] // 줌 레벨 15.05 이상에서는 'min_height' 속성 값을 적용
                    ],

                    'fill-extrusion-opacity': 0.6 // 건물의 투명도 (0.6, 반투명)
                }
            },
            labelLayerId
        );
    });
</script>

</body>
</html>

 

한국 멀리서 봤을때

 

확대하면 건물들이 3D형태로 나와있다.