본문 바로가기
API사용

[Mapbox] 맵 박스 눈/비 내리는 효과 예제

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

 

1. Mapbox 비 내리는 예제

  • 비내리는 효과 핵심코드
    /* 비 내리는 효과 */
    map.on('style.load', () => {
        // 지도 스타일이 로드될 때 실행되는 이벤트

        map.setConfigProperty('basemap', 'lightPreset', 'dawn');
        // 기본 지도 스타일을 'dawn' (새벽)으로 설정하여 분위기 조정

        // 특정 줌 레벨(zoom)에 따라 속성을 점진적으로 변화시키는 함수
        const zoomBasedReveal = (value) => {
            return [
                'interpolate', // 보간(interpolation) 적용하여 값이 부드럽게 변화하도록 설정
                ['linear'], // 선형(linear) 보간 방식 사용 (값이 일정하게 변화)
                ['zoom'], // 줌 레벨(zoom)을 기준으로 보간 적용
                11, 0.0, // 줌 레벨 11에서는 값이 0 (즉, 비가 보이지 않음)
                13, value // 줌 레벨 13에서는 'value' 값을 적용 (비가 보이기 시작)
            ];
        };

        // 지도에 비 효과 적용
        map.setRain({
            density: zoomBasedReveal(0.5), // 비의 밀도 (줌 11에서는 0, 줌 13에서는 0.5)
            intensity: 1.0, // 비의 강도 (값이 클수록 비가 더 강하게 표현됨)
            color: '#a8adbc', // 빗방울 색상 (회색빛의 차가운 색감)
            opacity: 0.7, // 비의 투명도 (1.0 = 불투명, 0.0 = 완전 투명)
            vignette: zoomBasedReveal(1.0), // 비 효과가 주변부에서 얼마나 약해지는지 조절
            'vignette-color': '#464646', // 비 주변부 흐림 효과의 색상
            direction: [0, 80], // 빗방울이 떨어지는 방향 (각도: 0°, 속도: 80)
            'droplet-size': [2.6, 18.2], // 빗방울 크기 범위 (최소 2.6px ~ 최대 18.2px)
            'distortion-strength': 0.7, // 빗방울이 바람 등에 의해 왜곡되는 정도
            'center-thinning': 0 // 화면 전체에 균일한 비 효과 적용 (0이면 중앙에서도 유지)
        });
    });

 

 

  • 비내리기 예제 전체 코드
<!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], // starting position [lng, lat]. Note that lat must be set between -90 and 90
        zoom: 9, // starting zoom
        pitch: 45,// 3D 시점으로 기울기 적용
        bearing: -17.6,//지도 회전 각도
        container: 'map',// 지도를 렌더링할 HTML 요소의 ID
        antialias: true //부드러운 렌더링을 위한 안티앨리어싱 활성화 (3D 그래픽 품질 향상)
    });

    /* 비 내리는 효과 */
    map.on('style.load', () => {
        // 지도 스타일이 로드될 때 실행되는 이벤트

        map.setConfigProperty('basemap', 'lightPreset', 'dawn');
        // 기본 지도 스타일을 'dawn' (새벽)으로 설정하여 분위기 조정

        // 특정 줌 레벨(zoom)에 따라 속성을 점진적으로 변화시키는 함수
        const zoomBasedReveal = (value) => {
            return [
                'interpolate', // 보간(interpolation) 적용하여 값이 부드럽게 변화하도록 설정
                ['linear'], // 선형(linear) 보간 방식 사용 (값이 일정하게 변화)
                ['zoom'], // 줌 레벨(zoom)을 기준으로 보간 적용
                11, 0.0, // 줌 레벨 11에서는 값이 0 (즉, 비가 보이지 않음)
                13, value // 줌 레벨 13에서는 'value' 값을 적용 (비가 보이기 시작)
            ];
        };

        // 지도에 비 효과 적용
        map.setRain({
            density: zoomBasedReveal(0.5), // 비의 밀도 (줌 11에서는 0, 줌 13에서는 0.5)
            intensity: 1.0, // 비의 강도 (값이 클수록 비가 더 강하게 표현됨)
            color: '#a8adbc', // 빗방울 색상 (회색빛의 차가운 색감)
            opacity: 0.7, // 비의 투명도 (1.0 = 불투명, 0.0 = 완전 투명)
            vignette: zoomBasedReveal(1.0), // 비 효과가 주변부에서 얼마나 약해지는지 조절
            'vignette-color': '#464646', // 비 주변부 흐림 효과의 색상
            direction: [0, 80], // 빗방울이 떨어지는 방향 (각도: 0°, 속도: 80)
            'droplet-size': [2.6, 18.2], // 빗방울 크기 범위 (최소 2.6px ~ 최대 18.2px)
            'distortion-strength': 0.7, // 빗방울이 바람 등에 의해 왜곡되는 정도
            'center-thinning': 0 // 화면 전체에 균일한 비 효과 적용 (0이면 중앙에서도 유지)
        });
    });


    /*건물 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>

결과

2. Mapbox 눈 내리는 예제

  • 눈내리기 핵심코드
    /* 눈 내리는 효과 */
    map.on('style.load', () => {
        // 지도 스타일이 로드될 때 실행되는 이벤트

        map.setConfigProperty('basemap', 'lightPreset', 'dusk');
        // 기본 지도 스타일을 'dusk' (황혼)으로 설정하여 눈 효과와 어울리는 분위기 연출

        // 특정 줌 레벨(zoom)에 따라 속성을 점진적으로 변화시키는 함수
        const zoomBasedReveal = (value) => {
            return [
                'interpolate', // 보간(interpolation) 적용하여 값이 부드럽게 변화하도록 설정
                ['linear'], // 선형(linear) 보간 방식 사용 (값이 일정하게 변화)
                ['zoom'], // 줌 레벨(zoom)을 기준으로 보간 적용
                11, 0.0, // 줌 레벨 11에서는 값이 0 (즉, 눈이 보이지 않음)
                13, value // 줌 레벨 13에서는 'value' 값을 적용 (눈이 보이기 시작)
            ];
        };

        // 지도에 눈 효과 적용
        map.setSnow({
            density: zoomBasedReveal(0.85), // 눈의 밀도 (줌 11에서는 0, 줌 13에서는 0.85)
            intensity: 1.0, // 눈이 내리는 강도 (값이 클수록 눈이 더 많이 내림)
            'center-thinning': 0.1, // 화면 중앙에서 눈이 적게 보이도록 조정 (0이면 전체 균일)
            direction: [0, 50], // 눈송이가 떨어지는 방향 (각도: 0°, 속도: 50)
            opacity: 1.0, // 눈의 투명도 (1.0 = 불투명, 0.0 = 완전 투명)
            color: `#ffffff`, // 눈송이 색상 (흰색)
            'flake-size': 0.71, // 눈송이 크기 (0.71px)
            vignette: zoomBasedReveal(0.3), // 눈 효과 주변 흐림 처리 (줌 11에서는 0, 줌 13에서는 0.3)
            'vignette-color': `#ffffff` // 흐림 효과 색상 (흰색)
        });
    });

 

 

  • 눈내리기 전체 코드
<!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 그래픽 품질 향상)
    });

    /* 눈 내리는 효과 */
    map.on('style.load', () => {
        // 지도 스타일이 로드될 때 실행되는 이벤트

        map.setConfigProperty('basemap', 'lightPreset', 'dusk');
        // 기본 지도 스타일을 'dusk' (황혼)으로 설정하여 눈 효과와 어울리는 분위기 연출

        // 특정 줌 레벨(zoom)에 따라 속성을 점진적으로 변화시키는 함수
        const zoomBasedReveal = (value) => {
            return [
                'interpolate', // 보간(interpolation) 적용하여 값이 부드럽게 변화하도록 설정
                ['linear'], // 선형(linear) 보간 방식 사용 (값이 일정하게 변화)
                ['zoom'], // 줌 레벨(zoom)을 기준으로 보간 적용
                11, 0.0, // 줌 레벨 11에서는 값이 0 (즉, 눈이 보이지 않음)
                13, value // 줌 레벨 13에서는 'value' 값을 적용 (눈이 보이기 시작)
            ];
        };

        // 지도에 눈 효과 적용
        map.setSnow({
            density: zoomBasedReveal(0.85), // 눈의 밀도 (줌 11에서는 0, 줌 13에서는 0.85)
            intensity: 1.0, // 눈이 내리는 강도 (값이 클수록 눈이 더 많이 내림)
            'center-thinning': 0.1, // 화면 중앙에서 눈이 적게 보이도록 조정 (0이면 전체 균일)
            direction: [0, 50], // 눈송이가 떨어지는 방향 (각도: 0°, 속도: 50)
            opacity: 1.0, // 눈의 투명도 (1.0 = 불투명, 0.0 = 완전 투명)
            color: `#ffffff`, // 눈송이 색상 (흰색)
            'flake-size': 0.71, // 눈송이 크기 (0.71px)
            vignette: zoomBasedReveal(0.3), // 눈 효과 주변 흐림 처리 (줌 11에서는 0, 줌 13에서는 0.3)
            'vignette-color': `#ffffff` // 흐림 효과 색상 (흰색)
        });
    });


    /*건물 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>

 

결과