Mapboxの3Dデータと土砂災害警戒区域をMapbox GL JSで重ねて表示してみました


はじめに

アウトプットイメージ

前提条件

  • Mapbox GL JSのバージョンはv2になります。
  • Mapboxのアクセストークンが必要になります。
  • Mapboxの3D地形及び3D建物の表示では下記のMapboxさんのドキュメンテーションを参考させていただきました。
  • Add 3D terrain to a map
  • 建物を3Dで表示
  • 土砂災害警戒区域には国土数値情報の土砂災害警戒区域データから全国(令和2年)のデータをダウンロードして用いています。
  • 具体には、ダウンロードしたデータの中から土砂災害警戒区域のポリゴンデータである、「A33-20_22Polygon.geojson」のgeojson形式のデータを用いています。

html

3Dterrain_3DBuildings_DisasterArea.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Mapbox3D地形+3D建物+土砂災害警戒区域(急傾斜地の崩壊・土石流・地滑り)</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.js"></script>
    <link rel="stylesheet" href="style.css" />
</head>

<body>
    <nav id="menu"></nav>
    <div id="map"></div>
    <script src="script.js"></script>
</body>

</html>

CSS

style.css
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }

#menu {
  background: #fff;
  position: absolute;
  z-index: 1;
  top: 10px;
  right: 10px;
  border-radius: 3px;
  width: 240px;
  border: 1px solid rgba(0,0,0,0.4);
}

#menu a {
  font-size: 13px;
  color: #404040;
  display: block;
  margin: 0;
  padding: 10px;
  text-decoration: none;
  border-bottom: 1px solid rgba(0,0,0,0.25);
  text-align: center;
}

#menu a:last-child {
  border: none;
}

#menu a:hover {
  background-color: #f8f8f8;
  color: #404040;
}

#menu a.active {
  background-color: #8DCF3F;
  color: #ffffff;
}

#menu a.active:hover {
  background: #79bb2b;
}

JavaScript

  • Mapboxのアクセストークンを入力してください。
  • 土砂災害警戒区域のレイヤの切り替え(フィルタ機能)では、geojsonファイルの属性の「現象の種類 (A33_001)」を用いています。
  • 現象種別コードはこちらで確認することができます。
script.js
mapboxgl.accessToken = 'Mapboxのアクセストークンを入力してください';
var map = new mapboxgl.Map({
    container: 'map',
    zoom: 16,
    center: [139.0835887, 35.1116931],
    pitch: 85,
    bearing: -45,
    style: 'mapbox://styles/mapbox-map-design/ckhqrf2tz0dt119ny6azh975y'
});

map.on('load', function () {
    map.addSource('mapbox-dem', {
        'type': 'raster-dem',
        'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
        'tileSize': 512,
        'maxzoom': 14
    });
    // add the DEM source as a terrain layer with exaggerated height
    map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });

    // add a sky layer that will show when the map is highly pitched
    map.addLayer({
        'id': 'sky',
        'type': 'sky',
        'paint': {
            'sky-type': 'atmosphere',
            'sky-atmosphere-sun': [0.0, 0.0],
            'sky-atmosphere-sun-intensity': 15
        }
    });

    // 既存の3D建物レイヤを追加
    map.addLayer({
        "id": "3d-buildings",
        "source": "composite",
        "source-layer": "building",
        "filter": ["==", "extrude", "true"],
        "type": "fill-extrusion",
        "minzoom": 10,
        "paint": {
            "fill-extrusion-color": "#ffffff",
            "fill-extrusion-height": [
                "interpolate", ["linear"], ["zoom"],
                10, 0,
                14.05, ["get", "height"]
            ],
            "fill-extrusion-base": [
                "interpolate", ["linear"], ["zoom"],
                10, 0,
                14.05, ["get", "min_height"]
            ],
            "fill-extrusion-opacity": 1.0
        }
    });
    //土砂災害計画区域ポリゴン追加
    map.addSource("MapPolygon", {
        type: "geojson",
        data: "data/A33-20_22Polygon.geojson"
    });
    //地滑り
    map.addLayer({
        id: "MapPolygon3",
        type: "fill",
        source: "MapPolygon",
        layout: {},
        paint: {
            "fill-color": "#ffa500",
            "fill-opacity": 0.5
        },
        filter: ["==", "A33_001", "3"]
    });
    //土石流
    map.addLayer({
        id: "MapPolygon2",
        type: "fill",
        source: "MapPolygon",
        layout: {},
        paint: {
            "fill-color": "#ffff00",
            "fill-opacity": 0.5
        },
        filter: ["==", "A33_001", "2"]
    });
    //急傾斜地の崩壊
    map.addLayer({
        id: "MapPolygon1",
        type: "fill",
        source: "MapPolygon",
        layout: {},
        paint: {
            "fill-color": "#ff00ff",
            "fill-opacity": 0.5
        },
        filter: ["==", "A33_001", "1"]
    });
    //崩壊地等分布図ポリゴン追加
    map.addSource("MapPolygon2", {
        type: "geojson",
        data: "data/Collapsed_Area_20210706.geojson"
    });
    map.addLayer({
        id: "MapPolygon4",
        type: "line",
        source: "MapPolygon2",
        layout: {},
        paint: {
            "line-color": "#ff0000",
            "line-width": 3
        },
    });

    // レイヤ設定
    var Map_AddLayer = {
        MapPolygon1: "土砂災害警戒区域-急傾斜地の崩壊",
        MapPolygon2: "土砂災害警戒区域-土石流",
        MapPolygon3: "土砂災害警戒区域-地滑り"
    };

    // レイヤメニュー作成
    for (var i = 0; i < Object.keys(Map_AddLayer).length; i++) {
        // レイヤID取得
        var id = Object.keys(Map_AddLayer)[i];
        // aタグ作成
        var link = document.createElement("a");
        link.href = "#";
        // id追加
        link.id = id;
        // 名称追加
        link.textContent = Map_AddLayer[id];

        // 初期表示全て表示
        link.className = "active";

        // aタグクリック処理
        link.onclick = function (e) {
            // id取得
            var clickedLayer = this.id;
            e.preventDefault();
            e.stopPropagation();

            // ON/OFF状態取得
            var visibility = map.getLayoutProperty(clickedLayer, "visibility");

            // ON/OFF判断
            if (visibility === 'visible') {
                // クリックしたレイヤを非表示
                map.setLayoutProperty(clickedLayer, 'visibility', 'none');
                this.className = '';
            } else {
                // クリックしたレイヤを表示
                map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
                this.className = 'active';
            }
        };

        // レイヤメニューにレイヤ追加
        var layers = document.getElementById("menu");
        layers.appendChild(link);
    }

});


// コントロール関係表示
var nav = new mapboxgl.NavigationControl();
map.addControl(nav, 'top-left');

// スケール表示
map.addControl(new mapboxgl.ScaleControl({
    maxWidth: 200,
    unit: 'metric'
}));

参考文献