React Leafletを使用してGeoJSONファイルを読み込み地図に町丁目ポリゴンを表示する

## 概要説明
React Leafletを使って地図の表示から町丁目ポリゴンの表示まで行います。
Node.jsはインストール済みの想定となります。

## 使用したもの
### React Leaflet

React Leafletは、ReactのコンポーネントとしてLeafletを使えるようにするためのライブラリです。

https://react-leaflet.js.org/

### Vite

Viteとは2020年に発表されたフロントエンドのビルドツールで、現代の Web プロジェクトのために、より速く無駄のない開発体験を提供することを目的としたビルドツールです。

https://ja.vitejs.dev/

### 町丁目ポリゴン
町丁目とは行政界の一つで「富士見町3丁目」「広尾1丁目」など「●丁目」で表わされる行政区画のことです。行政界は他には都道府県や市区町村、大字などがあります。
町丁目ポリゴンとは町丁目の境界データであり、e-stat で 小地域（町丁・字等別）という名称で公開されています。

今回使用する町丁目ポリゴンは、TerraMap API からレスポンスされたGeoJSONです。

<details><summary>レスポンスされたGeoJSONのサンプル</summary>

```PolygonSample.geojson
{
  "type": "FeatureCollection",
  "features": [
      {
          "type": "Feature",
          "properties": {
              "area": {
                  "area": 0.1875635128037082
              },
              "point_coordinates": [
                  139.66641,
                  35.67514
              ],
              "geocode": "13113002802"
          },
          "geometry": {
              "type": "MultiPolygon",
              "coordinates": [
                  [
                      [
                          [
                              139.671072468,
                              35.675472254
                          ],
                          [
                              139.671087008,
                              35.675455055
                          ],
                          [
                              139.668725237,
                              35.674791116
                          ],
                          [
                              139.665545327,
                              35.673872239
                          ],
                          [
                              139.661458827,
                              35.672694079
                          ],
                          [
                              139.661419451,
                              35.672851547
                          ],
                          [
                              139.661380745,
                              35.672937476
                          ],
                          [
                              139.661480105,
                              35.673177857
                          ],
                          [
                              139.661702716,
                              35.673487731
                          ],
                          [
                              139.661785305,
                              35.673651366
                          ],
                          [
                              139.661614923,
                              35.674287572
                          ],
                          [
                              139.6614962,
                              35.674380922
                          ],
                          [
                              139.661459656,
                              35.674408793
                          ],
                          [
                              139.662425327,
                              35.674739902
                          ],
                          [
                              139.66654409,
                              35.676248336
                          ],
                          [
                              139.667841199,
                              35.676698291
                          ],
                          [
                              139.670456339,
                              35.677651212
                          ],
                          [
                              139.670879432,
                              35.675730569
                          ],
                          [
                              139.670937715,
                              35.675631642
                          ],
                          [
                              139.671072468,
                              35.675472254
                          ]
                      ]
                  ]
              ]
          }
      }
  ]
}
```
</details>

https://www.mapmarketing.co.jp/terramap-api?grid=qiita&utm_source=qiita.com&utm_medium=referral&utm_campaign=qiita_react-leaflet-display-polygon_3ae68f41c79636622946_01

## Viteを使ってテンプレートを作成

はじめにnpm createコマンドを使用してアプリケーションのテンプレートを作成します。
```
npm create vite@latest
```
対話形式で入力や選択を行います。Project nameは「react_leaflet_polygon」、frameworkは「React」、variantは「JavaScript 」を選択します。
```
Need to install the following packages:
create-vite@5.5.2
Ok to proceed? (y) y
√ Project name: ... react_leaflet_polygon
√ Select a framework: » React
√ Select a variant: » JavaScript

Scaffolding project in C:\develop\react_leaflet_polygon...

Done. Now run:

  cd react_leaflet_polygon
  npm install
```
以上でテンプレートの作成が完了となり、ファイルが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/7d4f4e2e-5f8c-ce8a-43bc-4c0c3167a0f7.png)

## LeafletとReact Leafletのインストール
以下のコマンドを実行してLeafletとReact Leafletをインストールします。
```
npm install leaflet react-leaflet
```
## 地図の表示
App.jsxとindex.cssを以下のように編集します。
```javascript:App.jsx
import { MapContainer, TileLayer } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';

function App() {
  return (
    <MapContainer center={[35.67514, 139.66641]} zoom={16} style={{ height: '100vh' }}>
      <TileLayer
        attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
    </MapContainer>
  );
}

export default App
```
```javascript:index.css
body {
  height: 100%;
  margin: 0;
}
```
編集が完了したら以下のコマンドを実行して開発サーバーを立ち上げます。
```
npm run dev
```
URLを開くと地図が表示されます。

### 表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/086619d1-c881-0ed6-3ed1-eeb8a3baff32.png)

## GeoJSONファイルを読み込み町丁目ポリゴンを表示
続いてApp.jsxに以下のコードを追加してGeoJSONファイルを読み込み、地図上に町丁目のポリゴンを表示するようにします。
GeoJSONファイルはpublicフォルダに配置します。

```javaScript:App.jsx
import { MapContainer, TileLayer, GeoJSON } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import { useEffect, useState } from 'react';

function App() {
  const [geoJsonData, setGeoJsonData] = useState();

  useEffect(() => {
    // GeoJSONデータを取得
    fetch('PolygonSample.geojson')
      .then(response => response.json())
      .then(data => setGeoJsonData(data))
  }, []);
  
  // ポリゴンのスタイル設定
  const polygonStyleOptions = {
    color: "#810FCB",
    opacity: 1.0,
    weight: 2.0,
    fillColor: "#810FCB",
    fillOpacity: 0.5,
  };
  
  return (
    <MapContainer center={[35.67514, 139.66641]} zoom={16} style={{ height: '100vh' }}>
      <TileLayer
        attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      {geoJsonData && (
        <GeoJSON
          data={geoJsonData}
          style={polygonStyleOptions}
        />
      )}
    </MapContainer>
  );
}
export default App
```
### 表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/033b3e63-2f24-4536-392d-8263e1a329d4.png)