LoginSignup
0
0

LeafletでGeoJSONファイルを読み込み、人口で色分けを行ってみる

Last updated at Posted at 2024-05-21

はじめに

弊社の記事では、いろいろな地図ライブラリでGeoJSONのポリゴンを表示してきました。今回は、Leafletを用いて地図上に町丁目ポリゴンを表示し、人口総数によって色分けを行いたいと思います。

表示する町丁目ポリゴン(GeoJSON)

人口総数を属性に持つ町丁目ポリゴンについては、TerraMap APIから取得できるものを利用しました。

一部省略しておりますが、以下のようなGeoJSONファイルになります。
features[0].properties.data[0].value が人口総数の値になっています。

ChoPolygon.geojson
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "area": {
          "area": 0.23232962656232412
        },
        "data": [
          {
            "is_authorized": true,
            "stat_item_id": 15776,
            "stat_id": "001012000",
            "value": "1301"
          }
        ],
        "point_coordinates": [
          139.67882,
          35.662
        ],
        "geocode": "13110000104",
        "points": [
          [
            "東京都",
            "目黒区",
            "駒場4丁目"
          ]
        ]
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [
                139.674866628,
                35.664159828
              ],
              [
                139.675069068,
                35.664075835
              ],
              
              .... 座標を省略しています
              
            ]
          ]
        ]
      }
    },

    .... featureを省略しています
  ]
}

HTML

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>
      Leafletで地図に町丁目ポリゴンを表示し、人口総数で色分けを行ってみる
    </title>
    <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>
    <link rel="stylesheet" type="text/css" href="./style.css" />
  </head>
  <body>
    <div id="map" style="width: 100%; height: 95vh"></div>
    <script src="./index.js"></script>
  </body>
</html>

参考情報
https://leafletjs.com/examples/quick-start/

ポリゴン表示まで

OpenStreetMapの地図上に町丁目ポリゴンを表示し、クリックすることで人口総数をPopup表示させます。JavaScriptのコードは以下のようになります。

index.js
const map = L.map("map").setView([35.6727, 139.662], 13);

// 背景地図はOpenStreetMap
const tiles = L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
  maxZoom: 19,
  attribution:
    '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);

// GeoJSONのスタイル
const geoJsonStyle = {
  color: "#7a7a7a",
  fillColor: "#9a9a9a",
  fillOpacity: 0.5,
};

// onEachFeatureオプションを利用して属性データをPopup表示できるようにする
function onEachFeature(feature, layer) {
  // 属性データはfeature.propertiesの構成に従って参照する必要があります
  const prop = `住所:${feature.properties.points[0].join("")}<br>人口:${
    feature.properties.data[0].value
  }`;
  layer.bindPopup(prop);
}

// GeoJSONの内容を取得
fetch(`ChoPolygon.geojson`)
  .then((response) => response.json())
  .then((data) => {
    // GeoJSONのレイヤー
    L.geoJSON(data, {
      style: geoJsonStyle,
      onEachFeature, // 上記関数とリンク
    }).addTo(map);
  });

表示結果
ChoPolygon.png

参考情報
https://leafletjs.com/examples/geojson/

ポリゴンの色付け

続きまして、人口総数の値によってポリゴンの色分けを行います。基本的には Interactive Choropleth Map を参考にして作成しました。

index.jsのgeoJsonStyle宣言部分を以下のように差し替えます。

// 人口総数による配色
function getColor(d) {
  return d > 7000
    ? "#800026"
    : d > 6000
    ? "#BD0026"
    : d > 5000
    ? "#E31A1C"
    : d > 4000
    ? "#FC4E2A"
    : d > 3000
    ? "#FD8D3C"
    : d > 2000
    ? "#FEB24C"
    : d > 1000
    ? "#FED976"
    : "#FFEDA0";
}
// GeoJSONのスタイル
function geoJsonStyle(feature) {
  return {
    fillColor: getColor(feature.properties.data[0].value),
    weight: 1,
    opacity: 1,
    color: "white",
    dashArray: "3",
    fillOpacity: 0.7,
  };
}

表示結果
ChoPolygon2.png

凡例作成

Interactive Choropleth Map に倣って凡例も作成してみます。index.jsの末尾に以下コードを追記します。

const legend = L.control({ position: "bottomright" });

legend.onAdd = function () {
  const div = L.DomUtil.create("div", "info legend");
  const grades = [0, 1000, 2000, 3000, 4000, 5000, 6000, 7000];
  const labels = [];

  for (let i = 0; i < grades.length; i++) {
    const from = grades[i];
    const to = grades[i + 1];

    labels.push(
      `<i style="background:${getColor(from + 1)}"></i> ${from}${
        to ? `&ndash;${to}` : "+"
      }`
    );
  }

  div.innerHTML = labels.join("<br>");
  return div;
};

legend.addTo(map);

CSSファイルにも以下の記述を行います。

style.css
.info {
  padding: 6px 8px;
  font: 14px/16px Arial, Helvetica, sans-serif;
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
  border-radius: 5px;
}
.legend {
  text-align: left;
  line-height: 18px;
  color: #555;
}
.legend i {
  width: 18px;
  height: 18px;
  float: left;
  margin-right: 8px;
  opacity: 0.7;
}

完成画像

全体が上手くいくと、以下のような表示結果になります。

ChoPolygon3.png

記事は以上になります。
最後まで読んでいただきましてありがとうございます。

0
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
0
0