ZENRINMapsAPIの気象コンテンツを地図に表示してみる

# はじめに
[前回](https://qiita.com/00b012deb7c8/items/e0a867d58731d765b16e)、地震の震源地の場所を地図に表示してみました

ZENRIN Maps APIにも地震情報を取得できるAPIがあるので、
今回はそちらを試してみようと思います

ZENRIN Maps APIの気象コンテンツを使用してみたい人向けの記事です

# ZENRIN Maps API の気象コンテンツ
ZENRIN Maps APIには以下７種のAPIが公開されています
- [地震情報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_earthquake_info.html)
- [台風情報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_typhoon_info.html)
- [津波情報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_tsunami_info.html)
- [警報注意報、土砂災害警戒情報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_warning_info.html)
- [天気情報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_weather_info.html)
- [詳細天気予報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_weather_detail_info.html)
- [週間天気予報](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_weather_week_info.html)

ZENRIN Maps APIの地震情報は、
地震ごとの各地の震度情報を取得できるようです
（前回の 震源リスト とは異なります

# 準備
ZENRIN Maps APIで地図を表示するためには APIキー が必要です
登録して取得しておきましょう

[無料トライアルページ](https://www.zenrin-datacom.net/solution/zenrin-maps-api/trial?fm_cp=6757baf3203e3a00bb118509&fm_mu=6763a16daffc44067d7d5f69&utm_campaign=6757baf3203e3a00bb118509&utm_medium=else&utm_source=Qiita65)
2ヶ月間無料で利用できます

# 結果
![9aada19d28d7518e4c95.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001795/20c29055-6aac-4fa3-8784-d12b65831d9f.png)

まず、表示したい地震発生日をカレンダーから指定します
日付を指定したら、その日付に発生した地震一覧(地震ID)がプルダウンに表示されます
地震IDを選択すると各地の震度を地図上に表示します

# コード全体
```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>地震情報</title>
    <style>
    </style>

    <script src="https://test-js.zmaps-api.com/zma_loader.js?key=[APIキー]&auth=referer"></script>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>

    <link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/ui/1.14.1/jquery-ui.js"></script>

    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div id="ZMap"></div>

    <div id="calendar">
      <div id="datepicker"></div>
    </div>

    <div class="select_wrapper">
      <select id="select-area" class='select' aria-label="select">
      </select>
    </div>

    <script>
      let map;
      let intensityList=Object(); // 震度情報を格納する変数


      ZMALoader.setOnLoad(function (mapOptions, error) {
        if (error) {
          console.error(error)
          return
        }

        const lat = 35.681406, lng = 139.767132;
        const mapElement = document.getElementById('ZMap');
        mapOptions.center = new ZDC.LatLng(lat, lng);

        mapOptions.minZoom = 4;
        mapOptions.maxZoom = 11;
        mapOptions.zoom = 8;

        map = new ZDC.Map(
          mapElement,
          mapOptions,
          function() {
            map.addControl(new ZDC.ZoomButton('top-right'));
            map.addControl(new ZDC.Compass('top-right'));
            map.addControl(new ZDC.ScaleBar('bottom-left'));

            $("#datepicker").datepicker({
              onSelect: function(dateText, inst) {
                params = {
                  'address_code': (Array.from({length: 47},(v, k)=>('00'+(k+1)).slice(-2))).join(','),
                  'search_level': 3,
                  'event_datefrom': dateText,
                  'event_dateto': dateText
                }
                // ZENRIN Maps APIの地震情報APIからデータを取得する
                map.requestAPI('/search/weather/search_earthquake_info', params, function(res){
                  obj = res.ret.message.result;

                  $('#select-area').empty();
                  map.removeAllWidgets();

                  Object.keys(obj).forEach(function (key) {
                    if( Array.isArray(obj[key]) ){
                      // プルダウンの選択リスト
                      $('<option>',{value: key, text: key}).appendTo($('#select-area'))

                      // 震度情報を格納
                      intensityList[key] = obj[key];
                    }
                  });
                });
              }
            });
            $("#datepicker").datepicker("option", "dateFormat", 'yymmdd' );

            $(document).on('change', '#select-area', function(){
              drawIntensity($(this).val());
            });

          },
          function() {
          }
        );
      })

      // 地図に震度の数値を表示
      const drawIntensity = (id) => {
        datas = [];
        intensityList[id].forEach((row, idx) => {
          datas.push({
            'lat': row.intensity.city.rep_point.lat,
            'lng': row.intensity.city.rep_point.lon,
            'intensity': row.intensity.city.max_intensity,
          });
        });

        // 震度の小さい順にソート
        // UserWidget の表示優先度が後に乗せたものが上に表示されるため
        datas.sort((a, b) => {
          return a.intensity.localeCompare(b.intensity, 'ja');
        });
        map.removeAllWidgets();

        for(row of datas){
          var widget = new ZDC.UserWidget(
            new ZDC.LatLng(row.lat, row.lng),
            {
              htmlSource: `<div class="intensity i${row.intensity}">${row.intensity}</div>`,
              offset: new ZDC.Point(-20, -20),
              propagation: true
            }
          );
          map.addWidget(widget);
        }
      }
    </script>
  </body>
</html>
```

<details><summary>CSSはコチラ</summary>

```CSS
body {margin: 0; padding: 0;}
#ZMap {position: absolute; top: 0; bottom: 0; width: 100%;}

.intensity{
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  border: 2px solid #fff;
  font-size: 125%;
  font-weight: 700;
}
.intensity.i1{
  background: #bcbbbb;
  color: #393939;
}
.intensity.i2{
  background: #4cc4e7;
}
.intensity.i3{
  background: #4c53e7;
}
.intensity.i4{
  background: #d9dc2b;
  color: #393939;
}
.intensity.i5-{
  background: #facd6d;
  color: #393939;
}
.intensity.i5\+{
  background: #f9b627;
  color: #393939;
}
.intensity.i6-{
  background: #f79d76;
}
.intensity.i6\+{
  background: #fc7338;
}
.intensity.i7{
  background: #ff1c1c;
}

#calendar{
  position: absolute;
  top: 10px;
  left: 20px;
}


select {
  -webkit-appearance: none;
  appearance: none;
}
select::-ms-expand {
  display: none;
}

.select_wrapper {
  position: absolute;
  top: 10px;
  left: 310px;
  width: 160px;
}
.select_wrapper::after {
  position: absolute;
  top: 30%;
  right: 15px;
  width: 10px;
  height: 10px;
  border-top: 3px solid #333333;
  border-right: 3px solid #333333;
  -webkit-transform: rotate(135deg);
          transform: rotate(135deg);
  pointer-events: none;
  content: ""; 
}
.select {
  appearance: none;
  width: 160px;
  height: 45px;
  background-color: #ffffff;
  border: none;
  padding: 10px;
  cursor: pointer;
}

```
</details>


# 解説
## 日付の取得
```html
<link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.14.1/jquery-ui.js"></script>
```
カレンダーの表示と日付の取得に jquery-ui の datepicker を使用します

## 地震情報の取得
```javascript
$("#datepicker").datepicker({
  onSelect: function(dateText, inst) {
    params = {
      // 全国の情報を種痘するために都道府県コードをすべて指定する
      'address_code': (Array.from({length: 47},(v, k)=>('00'+(k+1)).slice(-2))).join(','),
      'search_level': 3,
      'event_datefrom': dateText, // 日付
      'event_dateto': dateText // 日付
    }
    // ZENRIN Maps APIの地震情報APIからデータを取得する
    map.requestAPI('/search/weather/search_earthquake_info', params, function(res){
      obj = res.ret.message.result;

      $('#select-area').empty();
      map.removeAllWidgets();

      // APIから一覧を取得したら、プルダウンに"地震ID"をセット
      // 併せて、取得した震度情報を変数に格納しておく
      Object.keys(obj).forEach(function (key) {
        if( Array.isArray(obj[key]) ){
          // プルダウンの選択リスト
          $('<option>',{value: key, text: key}).appendTo($('#select-area'))

          // 震度情報を格納
          intensityList[key] = obj[key];
        }
      });
    });
  }
});
```
ZENRIN Maps APIから地震情報を取得します
datepickerで日付を取得し、その日付をAPIリクエストのパラメータにセットしています
例では１日（指定日当日）を指定しています

パラメータの詳しい説明は[ドキュメント](https://developers.zmaps-api.com/v20/reference/webAPI/weather/search_earthquake_info.html)を参照してください

:::note info
javascript内からZENRIN Maps APIを使用するには、
map.requestAPI()という機能が用意されてますので、これを利用しています

[map.requestAPI()](https://developers.zmaps-api.com/v20/reference/javascriptAPI/map.html)
:::


## 地図に震度を表示
```javascript
// 地図に震度の数値を表示
const drawIntensity = (id) => {
  datas = [];
  intensityList[id].forEach((row, idx) => {
    datas.push({
      'lat': row.intensity.city.rep_point.lat,
      'lng': row.intensity.city.rep_point.lon,
      'intensity': row.intensity.city.max_intensity,
    });
  });

  // 震度の小さい順にソート
  // UserWidget の表示優先度が後に乗せたものが上に表示されるため
  datas.sort((a, b) => {
    return a.intensity.localeCompare(b.intensity, 'ja');
  });
  // 別の震度IDの震度情報が地図上に残らないようにすべてのwidgetを削除する
  map.removeAllWidgets();

  for(row of datas){
    // 震度の数値を表示するためのウィジェットを作成
    var widget = new ZDC.UserWidget(
      new ZDC.LatLng(row.lat, row.lng),
      {
        htmlSource: `<div class="intensity i${row.intensity}">${row.intensity}</div>`,
        offset: new ZDC.Point(-20, -20),
        propagation: true // ウィジェット上の操作を背部の地図に伝播させる
      }
    ); 
    // 地図上にウィジェットを表示
    map.addWidget(widget);
  }
}

```

# まとめ
ZENRIN Maps APIの地震情報を取得して各地の震度を地図上に表示することができました

ZENRIN Maps APIの気象コンテンツ検索は、
指定する住所コード、緯度経度から地震情報を取得すること可能です

場所(住所コード/緯度経度)の指定が必須の検索APIなので、その辺りは使い手を選ぶかもしれませんね