こちらの記事は新型コロナ感染箇所マップを作ってみる【FastAPI/PostGIS/deck.gl(React)】(データ加工編)の続きです。
上の記事をご覧になってからお読みください!
Reactの環境構築
ここまででcsvの元データをAPIからGeoJSON形式で吐き出せるようになっていると思いますので、そのデータを利用して地図上にコロナウイルス感染者の位置を表示できるようにしていきましょう!
まずはReactのプロジェクトを簡単に作成できるcreate-react-app
を実行するためのNode.js
がインストールされているか確認しましょう
$node -v
v12.13.1
$npm -v
6.12.1
上記2つのコマンドを入力してバージョンの数字が表示されればインストールされています。
コマンドがないよー!なんて怒られた場合にはインストールされていませんのでNodebrewでNodeをインストールするなんかを参考にしてnodebrew
のインストール→nodebrew
からNode.js
をインストール→npm
のインストールを行っていきましょう!
npm
のインストールまで終わったらcovid_sample
に移動し、以下のコマンドでReactのプロジェクトを作成していきます。
$npm install -g create-react-app
$npx create-react-app .
これでcovid_sample
自体がReactのプロジェクトになります。(コマンド最後の.
はカレントディレクトリにプロジェクトを作成するという意味で、ここに何か任意の名前を入れると、covid_sample
以下にその名前でディレクトリが作成されます)
$npm start
のコマンド入力後、localhost:3000
へブラウザからアクセスし、以下のような画面が表示されればプロジェクトの作成成功です!
deck.glの環境構築
deck.glは自動車配車サービスのUberが作成した大規模なデータセットの視覚的・探索的データ分析のためのWebGLを利用したフレームワークで、React上で動作させることを想定されています。(最近はpureJSでもちゃんと動くみたいですが)
めっちゃかっこいいです。
データさえあれば、以下のサンプルのように地図上に美しくデータを表現することができます。
今回はこのdeck.glを利用して地図上にデータを表示させていきましょう!
(ちなみに!!!!!今回扱うデータはただのポイントデータ(箇所ごとに緯度経度の位置情報があるだけのデータ)なので上のサンプルのようにかっこよくはなりません!!!!!!!すいません!!!!)
deck.glを利用するために以下の2つのコマンドを入力しましょう。
$npm install deck.gl
$npm install react-map-gl
下のreact-map-gl
はこちらもUberが作ったもので、Mapbox GL JS
というWebGIS界隈では非常に有名なライブラリのReact用ラッパーになります。
今回は背景地図の表示に利用していきます。
これでいよいよ開発環境が整ったので、アプリケーションを作成していきましょう!
アプリケーションの作成
mapboxの登録とトークンの発行
mapboxとは、Google マップのようなサービスですが、JavaScriptやネイティブ用のSDKが公開されており、自由に、簡単にカスタマイズできる地図サービスのことです。
今回は背景地図としてmapboxを利用していきますので、トップページから会員登録・マイページに表示されるトークンをコピーしておいてください。
背景地図の表示
src
というディレクトリが出来ているはずなのでそちらに移動しましょう。
Reactのプロジェクトでは基本的にこのsrc
以下のファイル群をいじっていきます。
src
ディレクトリの構成は以下のような感じになっていると思いますが、今回編集するファイルはApp.js
のみになります。
.
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
└── setupTests.js
ということでゴリゴリ修正していきましょう!
// Reactのインポート
import React from 'react';
// deck.glを利用
import DeckGL from '@deck.gl/react';
// geojsonを使うのでGeoJsonLayerを利用
import {GeoJsonLayer} from '@deck.gl/layers';
// 背景地図の表示にMapbox GL JSのラッパーを利用
import {StaticMap, Popup} from 'react-map-gl';
// 先ほど取得したトークンを文字列で格納
const MAPBOX_ACCESS_TOKEN = <MAPBOX_ACCESS_TOKEN>;
// 初期表示位置などを指定
const initialViewState = {
longitude: 139.7212733,
latitude: 35.6606213,
zoom: 8,
pitch: 45,
bearing: 0
};
// 最近は関数ベースのコンポーネントが主流だが、サンプルに合わせてクラスベース
class App extends React.Component {
// コンストラクターでデータを格納するstateを定義
constructor(props) {
super(props);
this.state = {
geojsonPoint: null,
};
}
// コンポーネントがマウントされてから動作するメソッド
// APIにアクセスしてデータを取得しておく
componentDidMount() {
fetch("http://0.0.0.0:8000/")
.then(res => res.json())
.then(
(result) => {
this.setState({
geojsonPoint: result
});
console.log("result", result);
},
(error) => {
console.log(error)
}
)
}
// ポップアップを表示させるためのメソッド
_renderTooltip() {
// hoveredObjectはホバーしている地物の情報
const {hoveredObject} = this.state || {};
console.log("hoveredObject", hoveredObject);
if (hoveredObject !== undefined) {
return (
// react-map-glのPopupコンポーネントを利用してポップアップを表示
<Popup
longitude={hoveredObject.geometry.coordinates[0]}
latitude={hoveredObject.geometry.coordinates[1]}>
<div>
<p>id:{hoveredObject.properties.id}</p>
<p>年齢:{hoveredObject.properties.age}</p>
<p>確定日:{hoveredObject.properties.fixed_data}</p>
</div>
</Popup>
)
}
}
// レンダリング用のメソッド
render() {
// コンストラクターで定義したstateからGeoJSONを取得
const geojsonPoint = this.state.geojsonPoint;
console.log("geojsonPoint: ", geojsonPoint);
const layers = [
new GeoJsonLayer({
// 任意のid
id: 'point_layer',
// GeoJSONを指定
data: geojsonPoint,
// pointの半径
getRadius: d => 2000,
// 地物のカラーをRGBaで指定
// aは透過度で0~255から指定
getFillColor: d => [245, 36, 36, 150],
pickable: true,
// 地物にホバーした時に発生するイベント
// stateを更新する
onHover: info => this.setState({
hoveredObject: info.object,
})
}),
];
return (
<>
{/*DeckGLコンポーネントに必要な情報を渡す*/}
<DeckGL
initialViewState={initialViewState}
controller={true}
layers={layers}
>
{/*利用したいmapboxのスタイルとトークンを渡す*/}
<StaticMap
mapStyle="mapbox://styles/mapbox/dark-v9"
mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}>
{/*ポップアップ用の関数も入れる*/}
{this._renderTooltip()}
</StaticMap>
</DeckGL>
</>
);
}
}
export default App;
Reactの基本的な解説などは別記事に書こうと思っていますが、Reactでは基本的にコンポーネントの戻り値はJSXというJavaScript内にHTMLを埋め込むような記法で書いていきます。
なので、Appクラスのrenderメソッドの戻り値はHTMLのタグのようなものがずらっと並んでいます。
しかし、実際にはトランスパイルされてJavaScriptに変換されるので
<DeckGL initialViewState={initialViewState}></DeckGL>
のようにタグの中にpropsと呼ばれる変数のようなものを渡して表示を動的に切り替えることが出来ます!
その他、どういう処理を行なっているのか…という部分はコード中にコメントを書いているので参考にしてみてください!
注意する点としては
- 新型コロナ感染箇所マップを作ってみる【FastAPI/PostGIS/deck.gl(React)】(データ加工編)で作成した、dockerコンテナが立ち上がっているか
-
http://0.0.0.0:8000/
にアクセスしてGeoJSONが返ってくるか - mapboxのトークンは記入されているか
だけ気をつけてもらえればあとはちゃんと表示されるはずです!
ブラウザで表示させてみる
ここまで出来たらあとは表示させるだけです!
$npm start
でサーバーを起動させてlocalhost:3000
に接続してみましょう!
こんな感じで地図上にポイントが表示されて、ホバーすると情報が表示されるようになったと思います!!!
最後に
こんな感じで情報の収集・加工・配信・表示まで一連で行なってきましたが、データさえあれば簡単に可視化できるのが、最近のフレームワークの良いところですね!
また、データの加工段階でQGISなどのGISソフトなどを使えば都道府県ごとの人数をヒートマップで可視化などいろんなことができると思いますのでみなさんどんどんGISやっていきましょう!