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

# はじめに
- Mapboxの3D地形及び3D建物と土砂災害警戒区域をMapbox GL JS(v2)で重ねて表示してみました。
- [Mapboxの3D地形](https://docs.mapbox.com/mapbox-gl-js/example/add-terrain/)はMapbox GL JS(v2)で[新たに追加された機能](https://docs.mapbox.com/jp/mapbox-gl-js/overview/#v2%E3%81%AE%E6%96%B0%E6%A9%9F%E8%83%BD)になります。
- 土砂災害警戒区域には国土数値情報の[土砂災害警戒区域データ](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-A33-v1_4.html)を用いています。

# アウトプットイメージ
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MapboxGLJS(v2)の3Dマップに土砂災害警戒区域（急傾斜地、土石流、地滑り）を追加して、レイヤの切り替えができるようにしてみた。<a href="https://twitter.com/hashtag/Mapbox?src=hash&amp;ref_src=twsrc%5Etfw">#Mapbox</a> <a href="https://t.co/yaZGI20mCM">https://t.co/yaZGI20mCM</a> <a href="https://t.co/WmqMMT1n3S">pic.twitter.com/WmqMMT1n3S</a></p>&mdash; shi_works🌧 (@syanseto) <a href="https://twitter.com/syanseto/status/1416621740034170883?ref_src=twsrc%5Etfw">July 18, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 前提条件
- Mapbox GL JSのバージョンはv2になります。
- Mapboxのアクセストークンが必要になります。
- Mapboxの3D地形及び3D建物の表示では下記のMapboxさんのドキュメンテーションを参考させていただきました。
- [Add 3D terrain to a map](https://docs.mapbox.com/mapbox-gl-js/example/add-terrain/)
- [建物を3Dで表示](https://docs.mapbox.com/jp/mapbox-gl-js/example/3d-buildings/)
- 土砂災害警戒区域には国土数値情報の[土砂災害警戒区域データ](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-A33-v1_4.html)から全国（令和2年）のデータをダウンロードして用いています。
- 具体には、ダウンロードしたデータの中から土砂災害警戒区域のポリゴンデータである、「A33-20_22Polygon.geojson」のgeojson形式のデータを用いています。

# html
```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
```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）」を用いています。
- 現象種別コードは[こちらで確認](https://nlftp.mlit.go.jp/ksj/gml/codelist/CodeOfPhenomenon.html)することができます。

```javascript: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'
}));
```

# 参考文献
https://docs.mapbox.com/mapbox-gl-js/example/add-terrain/

https://docs.mapbox.com/jp/mapbox-gl-js/example/3d-buildings/