Maps JavaScript APIを使って地図を表示する


## はじめに
本記事では、Maps JavaScript APIを使用してGoogleマップをWebサイトやアプリ上で扱う方法について備忘録も兼ねて残しています。

### Google mapを埋め込む方法
Googleマップをサイトに埋め込む方法は大きく分けて二つです。

1. 通常のGoogle mapの「地図を埋め込む」からiframeタグをペーストする方法
2. Google Maps Platformが提供するAPIを使用する方法

方法①
お馴染みのGoogleマップから『共有』を選択して、『地図を埋め込む』からiframeタグをコピーする事ができます。これを任意のHTMLファイルに貼り付けることでGoogleマップを表示させることが出来ます。
この方法はとても簡単でかつ無料で使用することが出来ます。
ただ位置情報をサイトに埋め込むだけであれば、APIを必要は無いのでこの方法で十分かもしれません

方法②
Google Maps Platform というサービスからAPIを使用して、Webサイトやアプリ上で地図表示させる方法です。これらのAPIはJavaScriptなどのプログラミング言語を用いることで、方法①では出来ないような表示や処理をする事ができます。

本稿では、こちらの方法を主題に執筆していきたいと思います。

### APIを使う準備

Google Maps PlatformのAPIはGCPから有効にする事で使用できるので、先ずはGCPを使える状態にしましょう。主にGCPで最初に行う設定は以下の3点です。

1. 請求先アカウントを作成(この時点ではまだ課金されないのでご安心ください)
2. プロジェクトを作成
3. 作成したプロジェクト直下で『APIライブラリ』からMaps JavaScript APIを有効にする

最初に行う設定が終わったら、Maps JavaScript API の APIキーを発行しましょう。以下の公式のリファレンスを参照すると良いです。

[Get an API Key | Maps JavaScript API | Google Developers](https://developers.google.com/maps/documentation/javascript/get-api-key)

## ①基本的な使い方



```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>map</title>
    <style>
        #map {
          height: 100%;
        }
        html, body {
          height: 100%;
          margin: 0;
          padding: 0;
        }
      </style>
</head>

<body>
    <div id="map"></div>

    <script>
        const mapEle = document.getElementById('map');

        function initialize() {
            var location = { lat: 35.658746, lng: 139.745465 }//東京タワー
            // 地図初期化
            var map = new google.maps.Map(mapEle, {
                zoom: 15,
                center: location
            });
        };
    </script>
    <script defer src="https://maps.googleapis.com/maps/api/js?key={ YOUR_KEY }&callback=initialize"></script>
</body>
</html>
```

## コード解説

Maps JavaScript APIでマップを埋め込むためには、そのマップを入れ込む箱が必要です。
中身が空のdivを用意し、JavaScriptとcssで指定できるようにid属性を付けておきましょう。

下記の部分はAPIをロードするためのscriptタグになります。srcにAPIエンドポイント、パラメータにkeyとcallbackを記述します。keyの値の{YOUR_KEY}の部分を自分で取得したAPIキーに変更しましょう。

```html
<script defer src="https://maps.googleapis.com/maps/api/js?key={ YOUR_KEY }&callback=initialize"></script>
```

initialize関数はAPIがロードされた時に呼び出される関数になります。

この関数が呼び出されると、new演算子を用いて、Mapクラスからインスタンスを作成しGoogleマップを表示することができます。第一引数のElementには作成したdiv要素を、第二引数には任意のオプション設定します。しかし、マップの中心地を設定するcenterオプションは必須なので、事前に緯度経度を格納しておいたlocation変数を値とします。

## ②ストリートビューも使ってみる

同じ要領でストリートビューも表示させることが出来ます。

```jsx
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #map,
        #pano {
            float: left;
            height: 100%;
            width: 50%;
        }
        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <div id="pano"></div>

    <script>
        const mapEle = document.getElementById('map');
        const panoEle = document.getElementById('pano');

        function initialize() {
            var location = { lat: 35.658746, lng: 139.745465 }//東京タワー
            // Google Map
            var map = new google.maps.Map(mapEle, {
                zoom: 15,
                center: location
            });
            // StreetView
            var panorama = new google.maps.StreetViewPanorama(panoEle, {
                position: location,
                pov: {
                    heading: 34,
                    pitch: 10
                }
            });
            map.setStreetView(panorama);
        };
    </script>
    <script defer src="https://maps.googleapis.com/maps/api/js?key={ YOUR_KEY }&callback=initialize"></script>
</body>

</html>
```

## コード解説

Mapクラスのインスタンスを作成したように、StreetViewを表示したい時はStreetViewPanoramaクラスを使用します。

下記の部分は、mapオブジェクトが持つsetStreetViewメソッドを使用しています。
このメソッドは、引数にStreetViewPanoramaオブジェクトを入れるとストリートビューがマップに関連付けられます。マップ上にペグマン(黄色い人形)が表示され、ストリートビューとマップが相互に連動するようになります。

```jsx
map.setStreetView(panorama);
```

## ③ボタンを押したら進ませる

最後はボタンのクリックをイベントにして、マップ及びストリートビューを操作します。
まずは、divタグで囲まれたbuttonを追記します。

```html
<div>
	<button id="go">GO!!</button>
</div>
```

次に以下のコードを先ほどのinitialize関数の中に追記します。

```jsx
const go = document.getElementById('go');
go.addEventListener('click', () => {
	var currentPov = panorama.getPov();
	var link = panorama.getLinks();
	var dir = 360;
	var target = 0;
	link.forEach((element, index) => {
		var ans = Math.abs(currentPov.heading - element.heading);
		if(dir > ans){
			dir = ans;
			target = index;
		}
	});
	var pa = link[target]['pano'];
	panorama.setPov({
		heading: link[target].heading,
		pitch: 0
	});
	panorama.setPano(pa);
});
```

## コード解説
StreetViewPanoramaクラスのgetPovメソッドは現在のパノラマの視点を取得します。

同じくStreetViewPanoramaクラスのgetLinksメソッドは、ストリートビューに表示されるナビゲーションリンク(矢印のようなもの)の配列を取得することができます。

このナビゲーションリンクをforEachで一つ一つ確認し、現在向いている視点(方角)からもっとも近いナビゲーションリンクのindexをtarget変数に格納します。

setPovメソッドで選択したナビゲーションリンクと同じ方角を向くように設定し、setPanoメソッドでナビゲーションリンクで移動した先のパノラマを表示させます。