5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

直近の地震があった場所をZENRINMapsAPIで表示してみる

Posted at

はじめに

オープンデータの活用と ZENRIN Maps API の確認も兼ねて、
日本で発生した地震の震源地を地図に表示してみます

地理座標のあるデータをゼンリンの地図に表示してみたい人向けの記事です

データソース

直近の地震があった場所は
気象庁が公開している 震源リスト を使用します

執筆時の最新データ
※2025年03月12日の震源リスト

公開データはテキストベタ書きなので、取得してCSVにしました
ChatGPTなどでさくっと変換しましょう

~ % head csv/20250312.csv
年,月,日,時刻,緯度,経度,深さ(km),M,震央地名
2025,3,12,00:02:46.7,33°4.8'N,130°32.3'E,14.0,0.1,福岡県筑後地方
2025,3,12,00:04:16.2,35°11.0'N,133°5.2'E,13.0,1.5,島根県東部
2025,3,12,00:04:27.1,34°26.1'N,131°34.6'E,28.0,-0.1,山口県北部
2025,3,12,00:04:41.1,28°47.3'N,130°13.5'E,35.0,2.0,奄美大島北東沖
2025,3,12,00:06:6.2,37°22.4'N,136°59.1'E,8.0,1.3,石川県能登地方
2025,3,12,00:06:46.0,34°26.1'N,131°34.8'E,29.0,0.1,山口県北部
2025,3,12,00:09:33.7,36°18.8'N,141°2.9'E,50.0,1.2,茨城県沖
2025,3,12,00:15:47.4,38°22.5'N,142°20.6'E,32.0,1.0,宮城県沖
2025,3,12,00:18:15.0,35°4.4'N,135°42.9'E,9.0,0.5,京都府南部

※緯度経度の測地系は世界測地系のようです

結果

まずは結果を
e0a867d58731d765b16e.png

ZENRIN Maps API

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

無料トライアルページ
2ヶ月間無料で利用できます

構成

.
├── index.html
└── csv/
    └── 20250312.csv

コード全体

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>震源リスト</title>
    <style>
      body {margin: 0; padding: 0;}
      #ZMap {position: absolute; top: 0; bottom: 0; width: 100%;}
    </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>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.40/jquery.csv.min.js" integrity="sha512-Y8iWYJDo6HiTo5xtml1g4QqHtl/PO1w+dmUpQfQSOTqKNsMhExfyPN2ncNAe9JuJUSKzwK/b6oaNPop4MXzkwg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  </head>

  <body>
    <div id="ZMap"></div>

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

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

        mapOptions.minZoom = 3;
        mapOptions.maxZoom = 10;
        mapOptions.zoom = 6;

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

            getData().then((datas)=>{
              for(row of datas){
                var widget = new ZDC.Oval(
                    new ZDC.LatLng(row.latitude, row.longitude),
                    {x:5000 , y:5000},
                    {
                      fillPattern: 'none',
                      stroke: '#e34633',
                      strokeWidth: 2,
                      opacity: 0.9
                    }
                  );
                map.addWidget(widget);
              }
            });

          },
          function() {
          }
        );
      })

      const getData = async () => {
        return new Promise(function (resolve, reject) {
          $.ajax({
            type: 'GET',
            url: 'csv/20250312.csv',
            cache: false,
            dataType: 'text',
            success: function(csv){
              const rows = $.csv.toArrays(csv);

              const dms2deg = function(dms){
                return dms[0] + (dms[1] / 60) + (dms[2] / 3600)
              }

              const datas = [];
              rows.forEach((row, idx) => {
                if(idx != 0){
                  lat = row[4].split(/[°\']/);
                  lng = row[5].split(/[°\']/);
                  datas.push(
                    {
                      latitude: dms2deg([Number(lat[0]), Number(lat[1]), 0.0]),
                      longitude: dms2deg([Number(lng[0]), Number(lng[1]), 0.0]),
                      magnitude: Number(row[7])
                    }
                  )
                }
              })
              resolve(datas);
            }
          });
        });
      }
    </script>
  </body>
</html>


解説

CSVデータの読み込み

      const getData = async () => {
        return new Promise(function (resolve, reject) {
          $.ajax({
            type: 'GET',
            url: 'csv/20250312.csv',
            cache: false,
            dataType: 'text',
            success: function(csv){
              const rows = $.csv.toArrays(csv);

              const dms2deg = function(dms){
                return dms[0] + (dms[1] / 60) + (dms[2] / 3600)
              }

              const datas = [];
              rows.forEach((row, idx) => {
                if(idx != 0){
                  lat = row[4].split(/[°\']/);
                  lng = row[5].split(/[°\']/);
                  datas.push(
                    {
                      latitude: dms2deg([Number(lat[0]), Number(lat[1]), 0.0]),
                      longitude: dms2deg([Number(lng[0]), Number(lng[1]), 0.0]),
                      magnitude: Number(row[7])
                    }
                  )
                }
              })
              resolve(datas);
            }
          });
        });
      }

作成した震源リストのCSVデータを非同期で読み込みます
jquery.csv.jsを使用しています

緯度経度の単位変換

const dms2deg = function(dms){
    return dms[0] + (dms[1] / 60) + (dms[2] / 3600)
}

震源リストは 度分秒単位 となっているので、十進法度単位 に換算します
度(°)・分(')・秒(")
※今回の震源リストでは「秒」は使用していないようです

60秒 = 1分、60分 = 1度 なので、それぞれ割った値を加算します

十進度 = 度 + (分 ÷ 60) + (秒 ÷ 3600)

今回はjavascript内で変換していますが、事前に変換したCSVデータを用意しても良いでしょう

地図上に発生場所を表示

今回はZENRIN Maps APIにある楕円を作成する機能を使用して表示します

// 円を作成
var widget = new ZDC.Oval(
    new ZDC.LatLng(row.latitude, row.longitude), // 中心座標
    {x:5000 , y:5000}, // 円の半径メートル ※この場合縦横に半径5000mの円
    {
      fillPattern: 'none', // 円の塗りつぶし
      stroke: '#e34633', // 円の色
      strokeWidth: 2,
      opacity: 0.9
    }
  );
// 作成した円を地図に表示
map.addWidget(widget);

マグニチュードに併せて円のサイズと色を変えてみる

switch (true){
  case row.magnitude < 1:
    stroke = '#1b2ade';
    radius = 5000;
    break;
  case 1 <= row.magnitude && row.magnitude < 3:
    stroke = '#1ebc0b';
    radius = 20000;
    break;
  case 3 <= row.magnitude && row.magnitude < 5:
    stroke = '#ded51b';
    radius = 60000;
    break;
  case 5 <= row.magnitude:
    stroke = '#de271b';
    radius = 100000;
    break;
  default:
    stroke = '#e0e7e2';
    radius = 5000;
}

var widget = new ZDC.Oval(
    new ZDC.LatLng(row.latitude, row.longitude),
    {x:radius , y:radius},
    {
      fillPattern: 'none',
      stroke: stroke,
      strokeWidth: 2,
      opacity: 0.9
    }
  );
map.addWidget(widget);

switch文やif文で色や半径サイズを指定すればOKです
"深さ"も考慮すると面白いかもしれませんね

e0a867d58731d765b16e-2.png

まとめ

地図座標のあるデータをその場所を地図上に表示することができました
オープンデータの座標を扱う上で気にしておく点は、

  • 測地系(世界測地系/日本測地系)
  • 座標単位
  • 精度(今回で言えは"秒"の有無。同様に小数点以下の桁数も)
5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?