Vue.jsとamCharts 4を使って地図を表示する

# はじめに
この記事では[vue-cli](https://cli.vuejs.org/)がインストールされていることを前提に話を進めていきます。

各ライブラリのバージョンは下記の通りです。

- vue-cli: 3.7.0
- @amcharts/amcharts4: 4.4.6
- @amcharts/amcharts4-geodata: 4.1.5

「[amChartsVue.jsとamCharts 4を使って地図を表示する パート2](https://qiita.com/KaiShoya/items/4fbb5fedebdfd4820207)」書きました。
パート2では地図の一部だけを表示・除外する方法を紹介しています。


# amChartsとは？
いろんな種類のチャートとマップが使えるJavaScriptライブラリです。
詳しくは[公式サイト](https://www.amcharts.com/)のDemosを見てみてください。

The Productタブを覗いてみると
`amCharts 4`1つで地図を含むいろんなチャートを使えるようになります！
React, Angular, Vue, Ember等で動くように設計されているのですぐに使えます！
的なことが書いてありました。

> [原文]
> Wide selection of chart types in a single package
> It’s easy with amCharts 4 – all chart types, including geographical maps, come in a single, easy to understand product!
> No need to figure out product line up – just get amCharts 4 for everything.
> And since it was designed to work with modern web dev toolkits like React, Angular, Vue, Ember, it will just fall into place, right out of the box.

どれほど簡単に使えるのか試してみたいと思います。

# Mapを表示してみる
vue-cliを使ってvueプロジェクトを作成します。

```sh
$ vue create sample-map
$ cd sample-map
```

amChartsをインストールします。

```sh
$ yarn add @amcharts/amcharts4
$ yarn add @amcharts/amcharts4-geodata
```

サーバーを起動します。

```sh
$ yarn serve
```

## 世界地図を表示
![Screen Shot 2019-05-18 at 13.04.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36872/2e6a6a64-5683-baa0-0d9a-f8aaecf31424.png)

```App.vue
<template>
  <div id="chartdiv"></div>
</template>

<script>
import * as am4core from "@amcharts/amcharts4/core"
import * as am4maps from "@amcharts/amcharts4/maps"
// 世界地図のgeodataを取得
import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow"

export default {
  mounted() {
    let map = am4core.create("chartdiv", am4maps.MapChart)
    map.geodata = am4geodata_worldLow
    map.projection = new am4maps.projections.Miller()
    var polygonSeries = map.series.push(new am4maps.MapPolygonSeries())
    polygonSeries.useGeodata = true
  },
  beforeDestroy() {
    if (this.map) {
      this.map.dispose()
    }
  }
}
</script>
<style scoped>
#chartdiv {
  width: 100%;
  height: 600px;
}
</style>
```

とてもシンプルですね。

では中身を解説していきます。

amChartをインポートします。

```js
import * as am4core from "@amcharts/amcharts4/core"
import * as am4maps from "@amcharts/amcharts4/maps"
```

地図データ(geodata)をインポートします。
`worldLow`と`worldHigh`、`japanLow`と`japanHigh`といった感じで、`Low`と`High`の2種類が用意されているようです。
世界地図の他に、各国の地図や群の地図などを指定できるようです。
~~宮崎の地図を表示したかったんですが、指定の仕方がわからず。。~~
`include`を使って地図の一部のみを表示することができました。（`exclude`で除外）
詳しい使い方は「[amChartsVue.jsとamCharts 4を使って地図を表示する パート2](https://qiita.com/KaiShoya/items/4fbb5fedebdfd4820207)」をご覧ください。

```js
// 簡素な世界地図
import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow"
// 詳細な日本地図
import am4geodata_japanLow from "@amcharts/amcharts4-geodata/japanHigh"
// アメリカ カリフォルニア州
import am4geodata_region_usa_caLow from "@amcharts/amcharts4-geodata/region/usa/caLow";

```


ここでどの要素にどのチャートを描画するのかを指定します。
今回は地図を描画したいのでMapChartを指定しています。

```js
let map = am4core.create("chartdiv", am4maps.MapChart)
```

ここで世界地図の`geodata`を指定しています。
geodataは自前のものを使うこともできるようですが、今回はamChartsが提供しているものを使います。

```js
map.geodata = am4geodata_worldLow
```

世界地図の投影方法？を指定します。
どんな種類があるかは下記URLを見てください。
https://www.amcharts.com/docs/v4/chart-types/map/#Setting_projection
[追記] `map.projection`は必須ではなく、指定しない場合は`Equirectangular`になるそうです。
コードを削除すると画像を差し替える必要が出てくるため、残したままにしておきます。

```js
map.projection = new am4maps.projections.Miller()
```

地図を描画する際に1つ以上のpolygonSeriesを設定しないとダメだそうです。
今回はgeodataを使うので、`useGeodata`をtrueにします。

```js
var polygonSeries = map.series.push(new am4maps.MapPolygonSeries())
polygonSeries.useGeodata = true
```

## クリックしたら地図を拡大表示する
polygonSeriesに下記のイベントを登録することで簡単に実装ができるようです。

```js
polygonSeries.mapPolygons.template.events.on("hit", function(ev) {
  map.zoomToMapObject(ev.target)
})
```

試しに日本地図を表示し拡大してみます。
![ee0715a3-2ca1-4998-y5aa-27f5ad7473d2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36872/fd955457-1258-ddbc-a384-3f7dfdb9d97c.gif)


```App.vue
<script>
import * as am4core from "@amcharts/amcharts4/core"
import * as am4maps from "@amcharts/amcharts4/maps"
import am4geodata_japanLow from "@amcharts/amcharts4-geodata/japanLow"

export default {
  mounted() {
    let map = am4core.create("chartdiv", am4maps.MapChart)
    map.geodata = am4geodata_japanLow
    map.projection = new am4maps.projections.Miller()
    var polygonSeries = map.series.push(new am4maps.MapPolygonSeries())
    polygonSeries.useGeodata = true
    polygonSeries.mapPolygons.template.events.on("hit", function(ev) {
      map.zoomToMapObject(ev.target)
    })
  },
  beforeDestroy() {
    if (this.map) {
      this.map.dispose()
    }
  }
}
</script>
```

## [追記]座標を指定してマーカーを表示する



```App.vue
<script>
import * as am4core from "@amcharts/amcharts4/core"
import * as am4maps from "@amcharts/amcharts4/maps"
import am4geodata_worldLow from "@amcharts/amcharts4-geodata/japanHigh"

export default {
  mounted() {
    let map = am4core.create("chartdiv", am4maps.MapChart)
    map.geodata = am4geodata_worldLow
    map.projection = new am4maps.projections.Mercator()
    var polygonSeries = map.series.push(new am4maps.MapPolygonSeries())
    polygonSeries.useGeodata = true
    polygonSeries.mapPolygons.template.events.on("hit", function(ev) {
      map.zoomToMapObject(ev.target)
    })

    // マーカー用のインスタンス作成
    // https://www.amcharts.com/docs/v4/chart-types/map/#Image_series
    let imageSeries = map.series.push(new am4maps.MapImageSeries())
    imageSeries.sequencedInterpolation = true

    let imageSeriesTemplate = imageSeries.mapImages.template

    // マーカーの形を定義(丸を指定)
    let circle = imageSeriesTemplate.createChild(am4core.Circle)
    // マーカーの色
    circle.fill = am4core.color("orange")
    // マーカーのサイズ
    circle.radius = 10
    // 枠線の色
    circle.stroke = am4core.color("red")
    // 枠線のサイズ
    circle.strokeWidth = 2
    // ツールチップに表示するテキスト dataのtextを表示できる
    circle.tooltipText = "{title}"

    // imageSeriesTemplateのlatitute,longitude(緯度経度)と配列の要素を紐付け
    imageSeriesTemplate.propertyFields.latitude = "latitude"
    imageSeriesTemplate.propertyFields.longitude = "longitude"

    imageSeries.data = [{
      "title": "Miyazaki",
      "latitude": 31.9076761,
      "longitude": 131.4202441
    }]
  },
  beforeDestroy() {
    if (this.map) {
      this.map.dispose()
    }
  }
}
</script>
```

# おわり
とても簡単に地図を表示することができました。
地図チャートを使った日本語記事がなかったので、誰かの役に立てばと思い書いてみました。
~~時間があったら座標を指定してマーカーを設置するサンプルも追加しようと思います。~~ 追記しました。