2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

気象庁サイトを利用したビューアの作成 10 地点情報

2
Posted at

目次・全体的な注意点(第1回の記事)

気象庁ホームページで使用されている、geojson等の地理情報を紹介します

記事作成時に確認した範囲の情報です。仕様変更などの可能性もありますのでご了承ください

地域に関するデータ

「1次細分区域」「市町村等をまとめた地域」「2次細分区域」の詳細な説明は 過去の記事を参照ください

1次細分区域(class10s.json)

各府県の「北部」「南部」などの地域のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/class10s.json に格納されています

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [ 141.9412, 45.5215],
              [ 141.979, 45.4742],......
            ]
          ]
        ]
      },
      "properties": {
        "code": "011000",
        "name": "宗谷地方",
        "enName": "Soya Region"
      }
    },......
  ],......
}

nameは1次細分区域名ではなく都道府県名のため、注意が必要です(1次細分区域名をプロットしたい場合には、後に取り上げる area.json と組み合わせて使用する必要があります)

まとめた地域(class15s.json)

1次細分区域をさらに分割した地域(東京なら「23区西部」「23区東部」など)を表す「市町村等をまとめた地域」のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/class15s.json に格納されています
(ファイル名以外class10s.jsonと同様のため例は省略)

2次細分区域(class20s_{i}.json)

おおむね市町村を表す、2次細分区域のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/class20s_{i}.json に格納されています。(ファイル名以外class10s.jsonとほぼ同様のため例は省略)

{i}は0から9の番号です。どの緯度経度でどのデータを取得すればいいかは、次の relm.json に記載されています。

なお、1次細分区域についても同様の高精細なgeojsonデータ(class10s_{i}.json)が存在します。同様に、土砂災害警戒情報の発表地域を表す landslides_{i}.json というデータも存在します(2026年5月の防災気象情報の体系整理で2次細分区域と統一されるため、今後使用する機会はないと思われます)

詳細な地域データの分割境界の情報(relm.json)

2次細分区域(・1次細分区域・土砂災害警戒情報の発表地域)の地域データは、10の地域に分けて格納されています。どの緯度経度になったらどのデータが必要かという情報は https://www.jma.go.jp/bosai/common/const/relm.json に格納されています

[
  {"ne":[45.5569,148.8922],"sw":[41.3521,139.3344]}, // 0 北海道
  {"ne":[41.5559,142.0725],"sw":[38.7478,139.6932]}, // 1 北東北
  {"ne":[39.2086,141.6747],"sw":[36.7365,137.635]}, // 2 南東北・新潟
  {"ne":[37.1543,153.9864],"sw":[24.2254,138.3971]}, // 3 関東
  {"ne":[37.8553,139.1766],"sw":[34.5781,136.2439]}, // 4 北陸東海甲信
  {"ne":[36.2953,136.9877],"sw":[33.433,134.2527]}, // 5 近畿福井三重
  {"ne":[37.2429,134.8208],"sw":[32.7025,131.668]}, // 6 中国四国
  {"ne":[34.7987,132.4913],"sw":[31.9887,128.3437]}, // 7 山口・九州北部
  {"ne":[33.1944,131.8857],"sw":[27.0187,128.3955]}, // 8 九州南部
  {"ne":[27.8853,131.3312],"sw":[24.0456,122.9337]} // 9 沖縄
]

0番目が class20s_0.json の担当範囲、1番目がclass20s_1.json の担当範囲… です

気象分野で用いる地域の情報(area.json)

気象分野で用いる 地方>府県>1次細分区域>まとめた地域>2次細分区域(≒市町村) の名称や包含関係は https://www.jma.go.jp/bosai/common/const/area.json に格納されています

{
  ......
  "offices": {
    "100000": {
      "name": "群馬県",
      "enName": "Gunma",
      "officeName": "前橋地方気象台",
      "parent": "010300",
      "children": [ "100010", "100020"]
    },
    "110000": {
      "name": "埼玉県",
      "enName": "Saitama",
      "officeName": "熊谷地方気象台",
      "parent": "010300",
      "children": [ "110010", "110020", "110030"]
    },......
  },......
}

nameに名称、parentとchildrenに包含関係が記載されています

海域(marines.json)

海上警報で用いられる地域のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/marines.json に格納されています

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [ 143.7108, 50.53],
              [ 147.0, 49.7],......
            ],......
          ],......
        ]
      },
      "properties": {
        "code": "1010",
        "name": "サハリン東方海上",
        "enName": "SEA EAST OF SAKHALIN"
      }
    },......
  ]
}

地震の地域(earthquake.json)

震度速報などで用いられる地域のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/earthquake.json に格納されています

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [ 141.4039, 43.7378],
              [ 141.4173, 43.7112],......
            ],......
          ],......
        ]
      },
      "properties": {
        "code": "100"
      }
    },......
  ]
}

格納されている情報はポリゴンの緯度経度と地域コードのみで、地域名は格納されていないため、地域名等を表示する際は地震情報の電文と合わせて利用する必要がありそうです

津波の地域(tsunami.json)

津波警報などで用いられる地域のgeojsonデータは https://www.jma.go.jp/bosai/common/const/geojson/tsunami.json に格納されています

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiLineString",
        "coordinates": [
          [
            [ 145.5976, 43.2217],
            [ 145.609, 43.2112],......
          ],......
        ]
      },
      "properties": {
        "code": "100"
      }
    },......
  ]
}

地震情報同様、地域名は格納されていないため、地域名等を表示する際は津波警報等の電文と合わせて利用する必要がありそうです

地点に関するデータ

地方/都道府県/市町村の中心位置(xy.json)

各地方/都道府県/市町村(2次細分区域)の中心位置が https://www.jma.go.jp/bosai/common/const/xy.json に格納されています

県庁や市役所、気象官署の位置というわけではなく、位置的に各地域のおおむね真ん中辺りの位置が指定されています

おそらく あなたの街の防災情報等のページでどの位置にズームするかを判定するのに使用しているのかなと想像します(未検証)

{
  "offices": {
    "100000": [ 36.4853, 138.9971],
    "110000": [ 36.0034, 139.3614],
    ......
    "hoppo": [ 45.0743, 147.8582]
  },
  "class20s": {
    "1020100": [ 36.4366, 139.1324],
    "1020200": [ 36.3786, 138.9026],
    ......
    "hoppo": [ 45.0743, 147.8582]
  },
  "centers": {
    "010100": [ 43.3979, 142.566],
    "010200": [ 39.0916, 140.6649],
    ......
    "hoppo": [ 45.1243, 147.8582]
  }
}

アメダス(amedastable.json)

各アメダスの位置や名称は https://www.jma.go.jp/bosai/amedas/const/amedastable.json に格納されています

{
  "11001": {
    "type": "C",
    "elems": "11112010",
    "lat": [ 45, 31.2],
    "lon": [ 141, 56.1],
    "alt": 26,
    "kjName": "宗谷岬",
    "knName": "ソウヤミサキ",
    "enName": "Cape Soya"
  },
  "11016": {
    "type": "A",
    "elems": "11111111",
    "lat": [ 45, 24.9],
    "lon": [ 141, 40.7],
    "alt": 3,
    "kjName": "稚内",
    "knName": "ワッカナイ",
    "enName": "Wakkanai"
  },......
}

緯度経度は度分表記で表されます。typeやelemsの意味等詳しくは過去の記事をご覧ください

火山の位置(volcano_list.json)

気象庁が情報を発表している活火山の位置は https://www.jma.go.jp/bosai/volcano/const/volcano_list.json に保存されています

[
  {
    "code": "101",
    "latlon": [ "44.133", "145.161" ],
    "pointShift":   [ 0, -15],
    "pointShift18": [ 0, -20],
    "name_jp": "知床硫黄山",
    "name_en": "Shiretoko-Iozan"
  },
  {
    "code": "102",
    "latlon": [ "44.076",  "145.122" ],
    "pointShift":   [-22, 0],
    "pointShift18": [-37, 0],
    "name_jp": "羅臼岳",
    "name_en": "Rausudake"
  },......
]

緯度経度はなぜか文字列で格納されていますので、何らか計算して利用するような場合は注意してください。おそらく他の山と文字が被らないようにするための pointShift pointShift18 が定義されています

各種地図の表示サンプルページ

以上に列挙した地図を、leaflet.jsを利用して描画するサンプルページです

サンプルページ

サンプルページのソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>地図</title>
  <!-- https://leafletjs.com/ -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
     integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
     crossorigin=""/>
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
     integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
     crossorigin=""></script>
  <style>
    *{ font-family:sans-serif;}
    html, body{ width:100%; height:100%; margin:0; overflow:hidden;}
    body{ display:flex; flex-direction:column;}
    div#menu{ flex:0.01;}
    div#map{ flex:1; background:#3b4580;}
    .icon{ text-align:center; font-size:14px;}
    .textWhite{ color:white; font-weight:bold;}
    .borderBlack{ text-shadow:1px 1px 0 #000, -1px -1px 0 #000, -1px 1px 0 #000, 1px -1px 0 #000;}
  </style>
</head>
<body>
  <div id="menu">
    <select id="elem">
      <option value="none">(なし)</option>
      <option value="amedas">アメダス</option>
      <option value="areaLimits">詳細な地域データの分割境界</option>
      <option value="areaCenters">都道府県・市町村の中心位置</option>
      <option value="class10s">1次細分区域</option>
      <option value="class15s">市町村等をまとめた地域</option>
      <option value="class20s">2次細分区域(拡大してください)</option>
      <option value="seaAreas">海上警報の地域</option>
      <option value="quakeAreas">震度速報等で用いる地域</option>
      <option value="tsunamiCoasts">津波警報等で用いる地域</option>
      <option value="volcanoes">火山</option>
    </select>

  </div>
  <div id="map"></div>
  <script>
    "use strict";
    let globals = {"class20s":{}}, layers = {};
    let map = L.map('map').setView([35, 135], 5);

    initialize();

    // 地図の表示
    function initialize(){
      const panes = {"paneM1":-10,"paneM2":-20,"paneM3":-30}
      for( let pane in panes){
        map.createPane(pane).style.zIndex = panes[pane];
      }
      const jmaAttr = '<a href="https://www.jma.go.jp/jma/kishou/info/coment.html" target="_blank">気象庁</a>';
      const gsiAttr = '<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">国土地理院</a>';
      L.control.layers({
        "(なし)":L.tileLayer('./images/blank.png', { maxNativeZoom:18, maxZoom:18, minZoom:1, attribution:jmaAttr, pane:"paneM2"}),
        "気象庁地図(灰色)":L.tileLayer('https://www.jma.go.jp/tile/jma/gray-cities/{z}/{x}/{y}.png', { maxNativeZoom:11, maxZoom:18, minZoom:2, attribution:jmaAttr, pane:"paneM2"}).addTo(map),
        "気象庁地図(緑色)":L.tileLayer('https://www.jma.go.jp/tile/jma/green-cities/{z}/{x}/{y}.png', { maxNativeZoom:10, maxZoom:18, minZoom:2, attribution:jmaAttr, pane:"paneM2"}),
        "地理院地図(白地図)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png', { maxNativeZoom:14, maxZoom:18, minZoom:5, attribution:gsiAttr, pane:"paneM2"}),
        "地理院地図(陰影起伏図)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/hillshademap/{z}/{x}/{y}.png', { maxNativeZoom:16, maxZoom:18, minZoom:4, attribution:gsiAttr, pane:"paneM2"}),
        "地理院地図(標準地図)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', { maxNativeZoom:18, maxZoom:18, minZoom:4, attribution:gsiAttr, pane:"paneM2"}),
        "地理院地図(淡色)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', { maxNativeZoom:18, maxZoom:18, minZoom:4, attribution:gsiAttr, pane:"paneM2"}),
        "地理院地図(英語)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/english/{z}/{x}/{y}.png', { maxNativeZoom:11, maxZoom:18, minZoom:4, attribution:gsiAttr, pane:"paneM2"}),
        "地理院地図(写真)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg', { maxNativeZoom:18, maxZoom:18, minZoom:4, attribution:'<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">国土地理院</a>', pane:"paneM2"}),
        "地理院地図(色別標高)":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png', { maxNativeZoom:15, maxZoom:18, minZoom:4, attribution:gsiAttr, pane:"paneM2"}),
        "赤色立体":L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/sekishoku/{z}/{x}/{y}.png', { maxNativeZoom:14, maxZoom:18, minZoom:4, attribution:'<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">(株)アジア航測 | 国土地理院</a>', pane:"paneM2"}),
        "地質図":L.tileLayer('https://gbank.gsj.jp/seamless/v2/api/1.2/tiles/{z}/{y}/{x}.png', { maxNativeZoom:13, maxZoom:18, minZoom:4, attribution:'<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">産総研 | 国土地理院</a>', pane:"paneM2"}),
        "OpenStreetMap":L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxNativeZoom:18, maxZoom:18, minZoom:4, attribution:'c <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>', pane:"paneM2"})
      },{
        "行政界(レーダー)":L.tileLayer('https://www.jma.go.jp/bosai/jmatile/data/map/none/none/none/surf/mask/{z}/{x}/{y}.png', { maxNativeZoom:14, maxZoom:18, minZoom:3, attribution:jmaAttr, pane:"paneM1"}),
        "行政界(気象)":L.tileLayer('https://www.jma.go.jp/tile/jma/base/{z}/{x}/{y}.png', { maxNativeZoom:11, maxZoom:18, minZoom:2, attribution:jmaAttr, pane:"paneM1"}),
        "行政界(地震)":L.tileLayer('https://www.jma.go.jp/tile/jma/transparent-cities/{z}/{x}/{y}.png', { maxNativeZoom:11, maxZoom:18, minZoom:2, attribution:jmaAttr, pane:"paneM1"}),
        "行政界(衛星)":L.tileLayer('https://www.jma.go.jp/tile/jma/sat/{z}/{x}/{y}.png', { maxNativeZoom:6, maxZoom:18, minZoom:2, attribution:jmaAttr, pane:"paneM1"}),
      }).addTo(map);
      getPolygons();
    }

    function getPolygons(){
      let promises = [];
      let urls = {
        "amedas":"https://www.jma.go.jp/bosai/amedas/const/amedastable.json",
        "areas":"https://www.jma.go.jp/bosai/common/const/area.json",
        "areaLimits":"https://www.jma.go.jp/bosai/common/const/relm.json",
        "areaCenters":"https://www.jma.go.jp/bosai/common/const/xy.json",
        "class10s":"https://www.jma.go.jp/bosai/common/const/geojson/class10s.json",
        "class15s":"https://www.jma.go.jp/bosai/common/const/geojson/class15s.json",
        "seaAreas":"https://www.jma.go.jp/bosai/common/const/geojson/marines.json",
        "quakeAreas":"https://www.jma.go.jp/bosai/common/const/geojson/earthquake.json",
        "tsunamiCoasts":"https://www.jma.go.jp/bosai/common/const/geojson/tsunami.json",
        "volcanoes":"https://www.jma.go.jp/bosai/volcano/const/volcano_list.json"
      };
      
      for( let elemName in urls){
        promises.push(
          new Promise((resolve, reject) => {
            fetch(urls[elemName])
            .then((response) => response.json())
            .then((response) => {
              globals[elemName] = response;
              resolve(elemName);
            });
          })
        );
      }
      
      Promise.allSettled(promises).then((values) => {
        globals['areas']['quakeAreas'] = {"100":{"name":"石狩地方北部","kana":"いしかりちほうほくぶ"},"101":{"name":"石狩地方中部","kana":"いしかりちほうちゅうぶ"},"102":{"name":"石狩地方南部","kana":"いしかりちほうなんぶ"},"105":{"name":"渡島地方北部","kana":"おしまちほうほくぶ"},"106":{"name":"渡島地方東部","kana":"おしまちほうとうぶ"},"107":{"name":"渡島地方西部","kana":"おしまちほうせいぶ"},"110":{"name":"檜山地方","kana":"ひやまちほう"},"115":{"name":"後志地方北部","kana":"しりべしちほうほくぶ"},"116":{"name":"後志地方東部","kana":"しりべしちほうとうぶ"},"117":{"name":"後志地方西部","kana":"しりべしちほうせいぶ"},"119":{"name":"北海道奥尻島","kana":"ほっかいどうおくしりとう"},"120":{"name":"空知地方北部","kana":"そらちちほうほくぶ"},"121":{"name":"空知地方中部","kana":"そらちちほうちゅうぶ"},"122":{"name":"空知地方南部","kana":"そらちちほうなんぶ"},"125":{"name":"上川地方北部","kana":"かみかわちほうほくぶ"},"126":{"name":"上川地方中部","kana":"かみかわちほうちゅうぶ"},"127":{"name":"上川地方南部","kana":"かみかわちほうなんぶ"},"130":{"name":"留萌地方中北部","kana":"るもいちほうちゅうほくぶ"},"131":{"name":"留萌地方南部","kana":"るもいちほうなんぶ"},"135":{"name":"宗谷地方北部","kana":"そうやちほうほくぶ"},"136":{"name":"宗谷地方南部","kana":"そうやちほうなんぶ"},"139":{"name":"北海道利尻礼文","kana":"ほっかいどうりしりれぶん"},"140":{"name":"網走地方","kana":"あばしりちほう"},"141":{"name":"北見地方","kana":"きたみちほう"},"142":{"name":"紋別地方","kana":"もんべつちほう"},"145":{"name":"胆振地方西部","kana":"いぶりちほうせいぶ"},"146":{"name":"胆振地方中東部","kana":"いぶりちほうちゅうとうぶ"},"150":{"name":"日高地方西部","kana":"ひだかちほうせいぶ"},"151":{"name":"日高地方中部","kana":"ひだかちほうちゅうぶ"},"152":{"name":"日高地方東部","kana":"ひだかちほうとうぶ"},"155":{"name":"十勝地方北部","kana":"とかちちほうほくぶ"},"156":{"name":"十勝地方中部","kana":"とかちちほうちゅうぶ"},"157":{"name":"十勝地方南部","kana":"とかちちほうなんぶ"},"160":{"name":"釧路地方北部","kana":"くしろちほうほくぶ"},"161":{"name":"釧路地方中南部","kana":"くしろちほうちゅうなんぶ"},"165":{"name":"根室地方北部","kana":"ねむろちほうほくぶ"},"166":{"name":"根室地方中部","kana":"ねむろちほうちゅうぶ"},"167":{"name":"根室地方南部","kana":"ねむろちほうなんぶ"},"200":{"name":"青森県津軽北部","kana":"あおもりけんつがるほくぶ"},"201":{"name":"青森県津軽南部","kana":"あおもりけんつがるなんぶ"},"202":{"name":"青森県三八上北","kana":"あおもりけんさんぱちかみきた"},"203":{"name":"青森県下北","kana":"あおもりけんしもきた"},"210":{"name":"岩手県沿岸北部","kana":"いわてけんえんがんほくぶ"},"211":{"name":"岩手県沿岸南部","kana":"いわてけんえんがんなんぶ"},"212":{"name":"岩手県内陸北部","kana":"いわてけんないりくほくぶ"},"213":{"name":"岩手県内陸南部","kana":"いわてけんないりくなんぶ"},"220":{"name":"宮城県北部","kana":"みやぎけんほくぶ"},"221":{"name":"宮城県南部","kana":"みやぎけんなんぶ"},"222":{"name":"宮城県中部","kana":"みやぎけんちゅうぶ"},"230":{"name":"秋田県沿岸北部","kana":"あきたけんえんがんほくぶ"},"231":{"name":"秋田県沿岸南部","kana":"あきたけんえんがんなんぶ"},"232":{"name":"秋田県内陸北部","kana":"あきたけんないりくほくぶ"},"233":{"name":"秋田県内陸南部","kana":"あきたけんないりくなんぶ"},"240":{"name":"山形県庄内","kana":"やまがたけんしょうない"},"241":{"name":"山形県最上","kana":"やまがたけんもがみ"},"242":{"name":"山形県村山","kana":"やまがたけんむらやま"},"243":{"name":"山形県置賜","kana":"やまがたけんおきたま"},"250":{"name":"福島県中通り","kana":"ふくしまけんなかどおり"},"251":{"name":"福島県浜通り","kana":"ふくしまけんはまどおり"},"252":{"name":"福島県会津","kana":"ふくしまけんあいづ"},"300":{"name":"茨城県北部","kana":"いばらきけんほくぶ"},"301":{"name":"茨城県南部","kana":"いばらきけんなんぶ"},"310":{"name":"栃木県北部","kana":"とちぎけんほくぶ"},"311":{"name":"栃木県南部","kana":"とちぎけんなんぶ"},"320":{"name":"群馬県北部","kana":"ぐんまけんほくぶ"},"321":{"name":"群馬県南部","kana":"ぐんまけんなんぶ"},"330":{"name":"埼玉県北部","kana":"さいたまけんほくぶ"},"331":{"name":"埼玉県南部","kana":"さいたまけんなんぶ"},"332":{"name":"埼玉県秩父","kana":"さいたまけんちちぶ"},"340":{"name":"千葉県北東部","kana":"ちばけんほくとうぶ"},"341":{"name":"千葉県北西部","kana":"ちばけんほくせいぶ"},"342":{"name":"千葉県南部","kana":"ちばけんなんぶ"},"350":{"name":"東京都23区","kana":"とうきょうとにじゅうさんく"},"351":{"name":"東京都多摩東部","kana":"とうきょうとたまとうぶ"},"352":{"name":"東京都多摩西部","kana":"とうきょうとたませいぶ"},"354":{"name":"神津島","kana":"こうづしま"},"355":{"name":"伊豆大島","kana":"いずおおしま"},"356":{"name":"新島","kana":"にいじま"},"357":{"name":"三宅島","kana":"みやけじま"},"358":{"name":"八丈島","kana":"はちじょうじま"},"359":{"name":"小笠原","kana":"おがさわら"},"360":{"name":"神奈川県東部","kana":"かながわけんとうぶ"},"361":{"name":"神奈川県西部","kana":"かながわけんせいぶ"},"370":{"name":"新潟県上越","kana":"にいがたけんじょうえつ"},"371":{"name":"新潟県中越","kana":"にいがたけんちゅうえつ"},"372":{"name":"新潟県下越","kana":"にいがたけんかえつ"},"375":{"name":"新潟県佐渡","kana":"にいがたけんさど"},"380":{"name":"富山県東部","kana":"とやまけんとうぶ"},"381":{"name":"富山県西部","kana":"とやまけんせいぶ"},"390":{"name":"石川県能登","kana":"いしかわけんのと"},"391":{"name":"石川県加賀","kana":"いしかわけんかが"},"400":{"name":"福井県嶺北","kana":"ふくいけんれいほく"},"401":{"name":"福井県嶺南","kana":"ふくいけんれいなん"},"411":{"name":"山梨県中・西部","kana":"やまなしけんちゅうせいぶ"},"412":{"name":"山梨県東部・富士五湖","kana":"やまなしけんとうぶふじごこ"},"420":{"name":"長野県北部","kana":"ながのけんほくぶ"},"421":{"name":"長野県中部","kana":"ながのけんちゅうぶ"},"422":{"name":"長野県南部","kana":"ながのけんなんぶ"},"430":{"name":"岐阜県飛騨","kana":"ぎふけんひだ"},"431":{"name":"岐阜県美濃東部","kana":"ぎふけんみのとうぶ"},"432":{"name":"岐阜県美濃中西部","kana":"ぎふけんみのちゅうせいぶ"},"440":{"name":"静岡県伊豆","kana":"しずおかけんいず"},"441":{"name":"静岡県東部","kana":"しずおかけんとうぶ"},"442":{"name":"静岡県中部","kana":"しずおかけんちゅうぶ"},"443":{"name":"静岡県西部","kana":"しずおかけんせいぶ"},"450":{"name":"愛知県東部","kana":"あいちけんとうぶ"},"451":{"name":"愛知県西部","kana":"あいちけんせいぶ"},"460":{"name":"三重県北部","kana":"みえけんほくぶ"},"461":{"name":"三重県中部","kana":"みえけんちゅうぶ"},"462":{"name":"三重県南部","kana":"みえけんなんぶ"},"500":{"name":"滋賀県北部","kana":"しがけんほくぶ"},"501":{"name":"滋賀県南部","kana":"しがけんなんぶ"},"510":{"name":"京都府北部","kana":"きょうとふほくぶ"},"511":{"name":"京都府南部","kana":"きょうとふなんぶ"},"520":{"name":"大阪府北部","kana":"おおさかふほくぶ"},"521":{"name":"大阪府南部","kana":"おおさかふなんぶ"},"530":{"name":"兵庫県北部","kana":"ひょうごけんほくぶ"},"531":{"name":"兵庫県南東部","kana":"ひょうごけんなんとうぶ"},"532":{"name":"兵庫県南西部","kana":"ひょうごけんなんせいぶ"},"535":{"name":"兵庫県淡路島","kana":"ひょうごけんあわじしま"},"540":{"name":"奈良県","kana":"ならけん"},"550":{"name":"和歌山県北部","kana":"わかやまけんほくぶ"},"551":{"name":"和歌山県南部","kana":"わかやまけんなんぶ"},"560":{"name":"鳥取県東部","kana":"とっとりけんとうぶ"},"562":{"name":"鳥取県中部","kana":"とっとりけんちゅうぶ"},"563":{"name":"鳥取県西部","kana":"とっとりけんせいぶ"},"570":{"name":"島根県東部","kana":"しまねけんとうぶ"},"571":{"name":"島根県西部","kana":"しまねけんせいぶ"},"575":{"name":"島根県隠岐","kana":"しまねけんおき"},"580":{"name":"岡山県北部","kana":"おかやまけんほくぶ"},"581":{"name":"岡山県南部","kana":"おかやまけんなんぶ"},"590":{"name":"広島県北部","kana":"ひろしまけんほくぶ"},"591":{"name":"広島県南東部","kana":"ひろしまけんなんとうぶ"},"592":{"name":"広島県南西部","kana":"ひろしまけんなんせいぶ"},"600":{"name":"徳島県北部","kana":"とくしまけんほくぶ"},"601":{"name":"徳島県南部","kana":"とくしまけんなんぶ"},"610":{"name":"香川県東部","kana":"かがわけんとうぶ"},"611":{"name":"香川県西部","kana":"かがわけんせいぶ"},"620":{"name":"愛媛県東予","kana":"えひめけんとうよ"},"621":{"name":"愛媛県中予","kana":"えひめけんちゅうよ"},"622":{"name":"愛媛県南予","kana":"えひめけんなんよ"},"630":{"name":"高知県東部","kana":"こうちけんとうぶ"},"631":{"name":"高知県中部","kana":"こうちけんちゅうぶ"},"632":{"name":"高知県西部","kana":"こうちけんせいぶ"},"700":{"name":"山口県北部","kana":"やまぐちけんほくぶ"},"702":{"name":"山口県西部","kana":"やまぐちけんせいぶ"},"703":{"name":"山口県東部","kana":"やまぐちけんとうぶ"},"704":{"name":"山口県中部","kana":"やまぐちけんちゅうぶ"},"710":{"name":"福岡県福岡","kana":"ふくおかけんふくおか"},"711":{"name":"福岡県北九州","kana":"ふくおかけんきたきゅうしゅう"},"712":{"name":"福岡県筑豊","kana":"ふくおかけんちくほう"},"713":{"name":"福岡県筑後","kana":"ふくおかけんちくご"},"720":{"name":"佐賀県北部","kana":"さがけんほくぶ"},"721":{"name":"佐賀県南部","kana":"さがけんなんぶ"},"730":{"name":"長崎県北部","kana":"ながさきけんほくぶ"},"731":{"name":"長崎県南西部","kana":"ながさきけんなんせいぶ"},"732":{"name":"長崎県島原半島","kana":"ながさきけんしまばらはんとう"},"735":{"name":"長崎県対馬","kana":"ながさきけんつしま"},"736":{"name":"長崎県壱岐","kana":"ながさきけんいき"},"737":{"name":"長崎県五島","kana":"ながさきけんごとう"},"740":{"name":"熊本県阿蘇","kana":"くまもとけんあそ"},"741":{"name":"熊本県熊本","kana":"くまもとけんくまもと"},"742":{"name":"熊本県球磨","kana":"くまもとけんくま"},"743":{"name":"熊本県天草・芦北","kana":"くまもとけんあまくさあしきた"},"750":{"name":"大分県北部","kana":"おおいたけんほくぶ"},"751":{"name":"大分県中部","kana":"おおいたけんちゅうぶ"},"752":{"name":"大分県南部","kana":"おおいたけんなんぶ"},"753":{"name":"大分県西部","kana":"おおいたけんせいぶ"},"760":{"name":"宮崎県北部平野部","kana":"みやざきけんほくぶへいやぶ"},"761":{"name":"宮崎県北部山沿い","kana":"みやざきけんほくぶやまぞい"},"762":{"name":"宮崎県南部平野部","kana":"みやざきけんなんぶへいやぶ"},"763":{"name":"宮崎県南部山沿い","kana":"みやざきけんなんぶやまぞい"},"770":{"name":"鹿児島県薩摩","kana":"かごしまけんさつま"},"771":{"name":"鹿児島県大隅","kana":"かごしまけんおおすみ"},"774":{"name":"鹿児島県十島村","kana":"かごしまけんとしまむら"},"775":{"name":"鹿児島県甑島","kana":"かごしまけんこしきしま"},"776":{"name":"鹿児島県種子島","kana":"かごしまけんたねがしま"},"777":{"name":"鹿児島県屋久島","kana":"かごしまけんやくしま"},"778":{"name":"鹿児島県奄美北部","kana":"かごしまけんあまみほくぶ"},"779":{"name":"鹿児島県奄美南部","kana":"かごしまけんあまみなんぶ"},"800":{"name":"沖縄県本島北部","kana":"おきなわけんほんとうほくぶ"},"801":{"name":"沖縄県本島中南部","kana":"おきなわけんほんとうちゅうなんぶ"},"802":{"name":"沖縄県久米島","kana":"おきなわけんくめじま"},"803":{"name":"沖縄県大東島","kana":"おきなわけんだいとうじま"},"804":{"name":"沖縄県宮古島","kana":"おきなわけんみやこじま"},"805":{"name":"沖縄県石垣島","kana":"おきなわけんいしがきじま"},"806":{"name":"沖縄県与那国島","kana":"おきなわけんよなぐにじま"},"807":{"name":"沖縄県西表島","kana":"おきなわけんいりおもてじま"}};
        globals['areas']['tsunamiCoasts'] = {"100":{"name":"北海道太平洋沿岸東部","color":"#ff4b00"},"101":{"name":"北海道太平洋沿岸中部","color":"#03af7a"},"102":{"name":"北海道太平洋沿岸西部","color":"#005aff"},"110":{"name":"北海道日本海沿岸北部","color":"#ff4b00"},"111":{"name":"北海道日本海沿岸南部","color":"#03af7a"},"120":{"name":"オホーツク海沿岸","color":"#005aff"},"200":{"name":"青森県日本海沿岸","color":"#ff4b00"},"201":{"name":"青森県太平洋沿岸","color":"#03af7a"},"202":{"name":"陸奥湾","color":"#005aff"},"210":{"name":"岩手県","color":"#ff4b00"},"220":{"name":"宮城県","color":"#03af7a"},"230":{"name":"秋田県","color":"#005aff"},"240":{"name":"山形県","color":"#03af7a"},"250":{"name":"福島県","color":"#03af7a"},"300":{"name":"茨城県","color":"#005aff"},"310":{"name":"千葉県九十九里・外房","color":"#ff4b00"},"311":{"name":"千葉県内房","color":"#03af7a"},"312":{"name":"東京湾内湾","color":"#ff4b00"},"320":{"name":"伊豆諸島","color":"#005aff"},"321":{"name":"小笠原諸島","color":"#03af7a"},"330":{"name":"相模湾・三浦半島","color":"#005aff"},"340":{"name":"新潟県上中下越","color":"#ff4b00"},"341":{"name":"佐渡","color":"#03af7a"},"350":{"name":"富山県","color":"#005aff"},"360":{"name":"石川県能登","color":"#ff4b00"},"361":{"name":"石川県加賀","color":"#03af7a"},"370":{"name":"福井県","color":"#005aff"},"380":{"name":"静岡県","color":"#ff4b00"},"390":{"name":"愛知県外海","color":"#03af7a"},"391":{"name":"伊勢・三河湾","color":"#005aff"},"400":{"name":"三重県南部","color":"#ff4b00"},"500":{"name":"京都府","color":"#03af7a"},"510":{"name":"大阪府","color":"#005aff"},"520":{"name":"兵庫県北部","color":"#ff4b00"},"521":{"name":"兵庫県瀬戸内海沿岸","color":"#03af7a"},"522":{"name":"淡路島南部","color":"#005aff"},"530":{"name":"和歌山県","color":"#03af7a"},"540":{"name":"鳥取県","color":"#03af7a"},"550":{"name":"島根県出雲・石見","color":"#005aff"},"551":{"name":"隠岐","color":"#ff4b00"},"560":{"name":"岡山県","color":"#ff4b00"},"570":{"name":"広島県","color":"#005aff"},"580":{"name":"徳島県","color":"#ff4b00"},"590":{"name":"香川県","color":"#03af7a"},"600":{"name":"愛媛県宇和海沿岸","color":"#005aff"},"601":{"name":"愛媛県瀬戸内海沿岸","color":"#ff4b00"},"610":{"name":"高知県","color":"#03af7a"},"700":{"name":"山口県日本海沿岸","color":"#005aff"},"701":{"name":"山口県瀬戸内海沿岸","color":"#ff4b00"},"710":{"name":"福岡県瀬戸内海沿岸","color":"#03af7a"},"711":{"name":"福岡県日本海沿岸","color":"#005aff"},"712":{"name":"有明・八代海","color":"#ff4b00"},"720":{"name":"佐賀県北部","color":"#03af7a"},"730":{"name":"長崎県西方","color":"#005aff"},"731":{"name":"壱岐・対馬","color":"#ff4b00"},"740":{"name":"熊本県天草灘沿岸","color":"#03af7a"},"750":{"name":"大分県瀬戸内海沿岸","color":"#005aff"},"751":{"name":"大分県豊後水道沿岸","color":"#ff4b00"},"760":{"name":"宮崎県","color":"#03af7a"},"770":{"name":"鹿児島県東部","color":"#ff4b00"},"771":{"name":"種子島・屋久島地方","color":"#005aff"},"772":{"name":"奄美群島・トカラ列島","color":"#03af7a"},"773":{"name":"鹿児島県西部","color":"#005aff"},"800":{"name":"沖縄本島地方","color":"#ff4b00"},"801":{"name":"大東島地方","color":"#005aff"},"802":{"name":"宮古島・八重山地方","color":"#005aff"}};
        makeLayers();
      });
    }

    function makeLayers( report){
      layers['amedas'] = L.layerGroup();
      for( let amedasCode in globals['amedas']){
        let amedas = globals['amedas'][amedasCode];
        let name = amedas['kjName'];
        let ruby = amedas['knName'];
        let lat = amedas['lat'][0] + amedas['lat'][1]/60;
        let lon = amedas['lon'][0] + amedas['lon'][1]/60;
        let icon = L.divIcon({
          html:"●<br><ruby>" + name + "<rt>" + ruby + "</rt></ruby>",
          iconSize: [80,30], iconAnchor: [40,10], className:'icon textWhite borderBlack'
        });
        let marker = L.marker( [lat,lon], {icon:icon});
        layers['amedas'].addLayer( marker);
      }
      
      layers['areaLimits'] = L.layerGroup();
      for( let i in globals['areaLimits']){
        let areaLimit = globals['areaLimits'][i];
        let nn = areaLimit['ne'][0], ee = areaLimit['ne'][1], ss = areaLimit['sw'][0], ww = areaLimit['sw'][1];
        let polygon = L.polygon([[nn,ww],[nn,ee],[ss,ee],[ss,ww],[nn,ww]],{color:'#005aff'});
        layers['areaLimits'].addLayer( polygon);
        let lat = (nn + ss) / 2, lon = (ee + ww) / 2;
        let icon = L.divIcon({
          html:i,
          iconSize: [80,30], iconAnchor: [40,10], className:'icon textWhite'
        });
        let marker = L.marker( [lat,lon], {icon:icon});
        layers['areaLimits'].addLayer( marker);
      }

      layers['areaCenters'] = {};
      for( let areaType in globals['areaCenters']){
        layers['areaCenters'][areaType] = L.layerGroup();
        for( let areaCode in globals['areaCenters'][areaType]){
          let areaName = "";
          try{
            areaName = globals['areas'][areaType][areaCode]['name'];
            let kana = globals['areas'][areaType][areaCode]['kana'];
            if( kana!=undefined){
              areaName = "<ruby>" + areaName + "<rt>" + kana + "</rt></ruby>";
            }
          }catch(e){
            console.log( areaType, areaCode, e);
          }
          let latlon = globals['areaCenters'][areaType][areaCode];
          let icon = L.divIcon({
            html:areaName,
            iconSize: [160,30], iconAnchor: [80,10], className:'icon textWhite borderBlack'
          });
          let marker = L.marker( latlon, {icon:icon});
          layers['areaCenters'][areaType].addLayer( marker);
        }
      }

      for( let areaType of ['class10s','class15s','seaAreas','quakeAreas','tsunamiCoasts']){
        layers[areaType] = L.layerGroup();
        let polygons = 
        L.geoJSON(globals[areaType], {
            style:function (feature){
              if( areaType=="tsunamiCoasts"){
                return {color:globals['areas'][areaType][feature.properties.code]['color']};
              }else{
                return {color:'#005aff'};
              }
            }
        }).bindPopup(function (layer) {
            const areaCode = layer.feature.properties.code;
            if( globals['areas'][areaType][areaCode]==undefined){
              return layer.feature.properties.name;
            }else{
              return globals['areas'][areaType][areaCode]['name'];
            }
        });
        layers[areaType].addLayer( polygons);
        for( let feature of globals[areaType]['features']){
          let lat = 0, lon = 0, nn = -Infinity, ss = Infinity, ww = Infinity, ee = -Infinity, count = 0, areaName = feature['properties']['name'], areaCode = feature['properties']['code'];
          if( globals['areas'][areaType]!=undefined && globals['areas'][areaType][areaCode]!=undefined){
            areaName = globals['areas'][areaType][areaCode]['name'];
          }
          for( let coordinates of feature['geometry']['coordinates']){
            for( let coordinate of coordinates){
              for( let coord of coordinate){
                let lat0 = coord[1], lon0 = coord[0];
                if( !Array.isArray(coord)){
                  lat0 = coordinate[1];
                  lon0 = coordinate[0];
                }
                lat += lat0;
                lon += lon0;
                nn = Math.max( nn, lat0);
                ss = Math.min( ss, lat0);
                ww = Math.min( ww, lon0);
                ee = Math.max( ee, lon0);
                count++;
              }
            }
          }
          let latlon = [lat/count, lon/count];
          if( areaType=="seaAreas"){
            latlon = [(nn+ss)/2, (ww+ee)/2];
          }
          let icon = L.divIcon({
            html:areaName,
            iconSize: [120,30], iconAnchor: [60,10], className:'icon textWhite borderBlack'
          });
          let marker = L.marker( latlon, {icon:icon});
          layers[areaType].addLayer( marker);
        }
      }

      layers['volcanoes'] = L.layerGroup();
      for( let volcano of globals['volcanoes']){
        let name = volcano['name_jp'], latlon = volcano['latlon'];
        if( latlon==undefined){
          continue;
        }
        let icon = L.divIcon({
          html:"▲<br><ruby>" + name + "</ruby>",
          iconSize: [80,30], iconAnchor: [40,10], className:'icon textWhite borderBlack'
        });
        let marker = L.marker( latlon, {icon:icon});
        layers['volcanoes'].addLayer( marker);
      }

      layers['class20s'] = {};
      getDetailedPolygons();
    }

    document.getElementById("elem").addEventListener("change",function(e){
      getDetailedPolygons();
    });

    // 移動時
    map.on('moveend', function(){
      getDetailedPolygons();
    });

    function getDetailedPolygons(){
      let promises = [];
      let zoom = map.getZoom(), bounds = map.getBounds();
      if( 8<=zoom){
        for( let i in globals['areaLimits']){
          if( (globals['areaLimits'][i]['sw'][0]<=bounds['_northEast']['lat'] && bounds['_southWest']['lat']<=globals['areaLimits'][i]['ne'][0]) && (globals['areaLimits'][i]['sw'][1]<=bounds['_northEast']['lng'] && bounds['_southWest']['lng']<=globals['areaLimits'][i]['ne'][1])){
            if( globals['class20s'][i] == undefined){
              promises.push(
                new Promise((resolve, reject) => {
                  fetch("https://www.jma.go.jp/bosai/common/const/geojson/class20s_" + [i] + ".json")
                  .then((response) => response.json())
                  .then((areas) => {
                    globals['class20s'][i] = areas;
                    layers['class20s'][i] = L.layerGroup();
                    let polygons = 
                    L.geoJSON(globals['class20s'][i], {
                        style:{color:'#005aff'}
                    }).bindPopup(function (layer) {
                        const areaCode = layer.feature.properties.code;
                        if( globals['areas'][areaType][areaCode]==undefined){
                          return layer.feature.properties.name;
                        }else{
                          return globals['areas']['class20s'][areaCode]['name'];
                        }
                    });
                    layers['class20s'][i].addLayer( polygons);
                    for( let feature of globals['class20s'][i]['features']){
                      let areaName = feature['properties']['name'], areaCode = feature['properties']['code'];
                      if( globals['areas']['class20s'][areaCode]!=undefined){
                        areaName = globals['areas']['class20s'][areaCode]['name'];
                        if( globals['areas']['class20s'][areaCode]['kana']!=undefined){
                          let kana = globals['areas']['class20s'][areaCode]['kana'];
                          areaName = "<ruby>" + areaName + "<rt>" + kana + "</rt></ruby>";
                        }
                      }
                      let latlon = globals['areaCenters']['class20s'][areaCode];
                      let icon = L.divIcon({
                        html:areaName,
                        iconSize: [100,30], iconAnchor: [50,10], className:'icon textWhite borderBlack'
                      });
                      let marker = L.marker( latlon, {icon:icon});
                      layers['class20s'][i].addLayer( marker);
                    }
                    resolve( i);
                  });
                })
              );
            }
          }
        }
      }
      Promise.all(promises).then((values) => {
        controlLayers();
      }); 
    }

    function controlLayers(){
      let elem = document.getElementById("elem").value;
      let zoom = map.getZoom();
      console.log( {zoom});

      for( let layerName of ['amedas','areaLimits','class10s','class15s','seaAreas','quakeAreas','tsunamiCoasts','volcanoes']){
        if( elem==layerName){
          if( !map.hasLayer(layers[layerName])){
            map.addLayer(layers[layerName]);
          }
        }else if( map.hasLayer(layers[layerName])){
          map.removeLayer(layers[layerName]);
        }
      }

      if( elem=="areaCenters" && zoom<=6){
        if( !map.hasLayer(layers['areaCenters']['centers'])){
          map.addLayer(layers['areaCenters']['centers']);
        }
      }else if( map.hasLayer(layers['areaCenters']['centers'])){
        map.removeLayer( layers['areaCenters']['centers']);
      }
      if( elem=="areaCenters" && 7<=zoom && zoom<=8){
        if( !map.hasLayer(layers['areaCenters']['offices'])){
          map.addLayer(layers['areaCenters']['offices']);
        }
      }else if( map.hasLayer(layers['areaCenters']['offices'])){
        map.removeLayer( layers['areaCenters']['offices']);
      }
      if( elem=="areaCenters" && 9<=zoom){
        if( !map.hasLayer(layers['areaCenters']['class20s'])){
          map.addLayer(layers['areaCenters']['class20s']);
        }
      }else if( map.hasLayer(layers['areaCenters']['class20s'])){
        map.removeLayer( layers['areaCenters']['class20s']);
      }


      for( let i in layers['class20s']){
        if( elem=="class20s" && zoom>=8){
          if( !map.hasLayer(layers['class20s'][i])){
            map.addLayer(layers['class20s'][i]);
          }
        }else if( map.hasLayer(layers['class20s'][i])){
          map.removeLayer(layers['class20s'][i]);
        }
      }

    }
  </script>
</body>
</html>
2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?