DECK.GLを使ってGoogleMapタイムラインをビジュアライズしてみよう！#4　〜Mapコンポーネントの表示〜

DECK.GLを使ってGoogleMapのタイムラインをビジュアル化してみよう！の第４弾の記事です。

[前回](https://qiita.com/koeri3/items/c4c92408cf7aa0d54b7c)はDECK.GLのPathLayerを使って、データの描画を行いました。
今回はこれにマップコンポーネントを組み込んで表示させてみたいと思います。


# 目次
本記事は全５回に渡り説明していきます。

1. [ReactとDECK.GLの環境構築](https://qiita.com/koeri3/items/8dc468ad9f910bdf244b)
2. [基本的なReactのコードをブラウザで確認](https://qiita.com/koeri3/items/a245f7cb50e77ebf3167)
3. [DECK.GLを使った簡単なデータの表示](https://qiita.com/koeri3/items/c4c92408cf7aa0d54b7c)
4. マップコンポーネントの表示   **←今回はコレ**
5. [GoogleMapタイムラインデータ表示](https://qiita.com/koeri3/items/3578f1b9269721f27733)


## 前回のおさらい
[前回](https://qiita.com/koeri3/items/c4c92408cf7aa0d54b7c)は、App.jsx に下記のコードを書きました。

```jsx:App.js
import React from "react";
import DeckGL from "@deck.gl/react";
import { PathLayer } from "@deck.gl/layers";

// Viewport 初期設定
const viewState = {
  longitude: -122.5,
  latitude: 37.75,
  zoom: 11
};

// 描画する地理データ
const data = [
  {
    path: [
      [-122.45, 37.7],
      [-122.5, 37.8],
      [-122.6, 37.7]
    ]
  }
];

export default class App extends React.Component {
  render() {
    const layer = [
      new PathLayer({
        id: "path-layer",
        data,
        getPath: d => d.path,
        getWidth: 30
      })
    ];
    return <DeckGL viewState={viewState} layers={layer}></DeckGL>;
  }
}
```

## マップコンポーネント

DECK.GLはマップコンポーネントなしでも独立して動作しますが、地理データをビジュアライズするのに地図情報が表示されないのではおもしろくありませんよね。

DECK.GLと簡単に連携できるマップコンポーネントとして、GoogleMapと[Mapbox](https://mapbox.com/)の２つの選択肢がありますが、
今回はMapboxを使って描画したいと思います。

※マップコンポーネントの連携についての詳細は[こちら](https://deck.gl/#/documentation/getting-started/using-with-base-map)をご参照ください。

## Mapboxとは？

Mapboxとは、米カリフォルニア州サンフランシスコにある位置データプラットフォームです。要するに、GoogleMapのような地図サービスです。

最近はゼンリンと提携したり、「ソフトバンク・ビジョン・ファンド」から出資を受けたりと、日本での事業も強化しようとしているようです。

- 参考: [Mapbox.jp、日本で事業を開始](https://www.globenewswire.com/news-release/2019/07/18/1884391/0/en/Mapbox-jp-%E6%97%A5%E6%9C%AC%E3%81%A7%E4%BA%8B%E6%A5%AD%E3%82%92%E9%96%8B%E5%A7%8B.html)
- 参考: [ゼンリンがデータ提供したというMapboxを使ってみた](https://k-tai.watch.impress.co.jp/docs/column/minna/1177047.html)


Mapboxでは、GoogleMap同様開発者に便利なインターフェースがたくさん提供されています。
例えば、[Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/overview/)というJavaScriptライブラリが提供されていたり、
[mapbox-gl](https://www.npmjs.com/package/mapbox-gl)という名前でNodeパッケージも公開されています。

今回はReactコンポーネントとして利用できる[react-map-gl](https://uber.github.io/react-map-gl)を使ってMapboxを連携させましょう。

※MapboxのDocumentationは[こちら](https://docs.mapbox.com/)
- Mapbox GL JSの[Github](https://github.com/mapbox/mapbox-gl-js)
- react-map-glの[Github](https://github.com/uber/react-map-gl)


## Mapboxを連携させよう

### `react-map-gl`ライブラリのインストール
まず`react-map-gl`ライブラリをインストールします。

```

$ yarn add react-map-gl
yarn add v1.17.3
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > @testing-library/user-event@7.1.2" has unmet peer dependency "@testing-library/dom@>=5".
warning "react-scripts > @typescript-eslint/eslint-plugin > tsutils@3.17.1" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
[4/4] 🔨  Building fresh packages...
success Saved lockfile.

... （長いので省略）

├─ tinyqueue@2.0.3
├─ vt-pbf@3.1.1
└─ wgs84@0.0.0
✨  Done in 24.60s.
$ 
```

### MapGLコンポーネントのimport

インストールが終わったら、MapGLコンポーネントをimportしましょう。
また、Mapbox GL JS の css も import しておかないとwarningが出てしまうので、こちらもimportします。

```jsx:App.js(一部)
import React from "react";
import DeckGL from "@deck.gl/react";
import { PathLayer } from "@deck.gl/layers";
import MapGL from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";

```

### Mapbox のアクセストークン
Mapbox を使う場合は、 Mapbox のアクセストークンを埋め込む必要があります。

アクセストークンは、Mapboxにログインして、「Access tokens」の `+ Create a token` ボタンから作成することができます。

![Screen Shot 2019-12-19 at 22.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431109/bc7909b8-809b-1401-fdd1-08bf32400b4d.png)

こちらからログインしてください :point_right_tone1: https://account.mapbox.com/
※アカウントを持っていない人は、アカウントの作成が必要です


アクセストークンが取得できたら、下記のように`App.jsx`に書きます。
本来アクセストークンのような外部に漏れてはいけない情報は、`.env`ファイルなどの環境変数で管理した方が良いですが、
Mapboxには、指定したURLから発信されたリクエストに対してのみ機能する「制限付きトークン」を作成することができるので、これであればファイルに埋め込んでも問題ありませんね。

```jsx:App.js(一部)
// mapbox access token
const MAPBOX_ACCESS_TOKEN = "pk.eyJ1IjoiZ......."
```

### MapGLコンポーネントの追加
それでは最後にDeckGLにマップコンポーネントを組み込みます。
上記で定義したアクセストークンは`mapboxApiAccessToken`に渡します。

```jsx:App.js(一部)
    return (
      <DeckGL viewState={viewState} layers={layer}>
        <MapGL mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN} />
      </DeckGL>
    );
```

## ブラウザで表示
それではここまで書いたコードをブラウザで表示してみましょう！
`yarn start`コマンドで起動させると・・・

:point_down_tone2::point_down_tone2::point_down_tone2:

![Screen Shot 2019-12-19 at 22.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431109/b19b6368-1a0a-ca11-34c4-0c93b045a096.png)

地図の上にパスが表示されました！！:clap:


## 次回予告
[次回](https://qiita.com/koeri3/items/3578f1b9269721f27733)はいよいよGoogleMapタイムラインの表示を行います！


## App.jsxの全体像

```jsx:App.js
import React from "react";
import DeckGL from "@deck.gl/react";
import { PathLayer } from "@deck.gl/layers";
import MapGL from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";

// mapbox access token
const MAPBOX_ACCESS_TOKEN = "pk.eyJ1IjoiZ.......";

// Viewport 初期設定
const viewState = {
  longitude: -122.5,
  latitude: 37.75,
  zoom: 11
};

// 描画する地理データ
const data = [
  {
    path: [
      [-122.45, 37.7],
      [-122.5, 37.8],
      [-122.6, 37.7]
    ]
  }
];

export default class App extends React.Component {
  render() {
    const layer = [
      new PathLayer({
        id: "path-layer",
        data,
        getPath: d => d.path,
        getWidth: 30
      })
    ];
    return (
      <DeckGL viewState={viewState} layers={layer}>
        <MapGL mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN} />
      </DeckGL>
    );
  }
}

```