新料金体系のGoogle Maps Platformを使った標準的なUIの実現

#この記事は
新しい体系になったgoogleのmap関連APIとその料金体系を元に
googleのマップデータを使った標準的なUIの提供についてまとめたものです。

##この記事にない情報
×　GCPやAPIのアカウント作成からなど、導入のガイダンス
×　ストリートビューに関すること
×　Google map, place APIに関する技術的なこと

#マップを表示する
マップをサイトに表示する方法は以下の3つが考えられます。
１. インラインフレームタグでgoogle mapのサイトを埋め込む(Maps URLs)
2. Maps Static APIでStatic Map（画像）で取得する
3. Maps Javascript APIでDynamic Mapsを取得する

1は無料で使えるのと、日本の場合唯一公共交通機関の経路検索に対応しているのが強み
何度も表示する部分や都市部の経路検索を表示する場合はこれか。
優先順位として一番高い気がしますね。

２は比較的低コストで使える（1,000リクエストで2ドル[^1]）のと、
プレイス名, 住所, 緯度経度のいずれかを使って画像の上にピンを立てることが可能。
複数の拠点の位置関係を一覧化したい場合にはこれか。
基本的には緯度経度が手元のデータベースにあるとベストだと思うが、
有名なスポットならプレイス名、辺鄙な場所でなければ住所でもいけるので
データベースを頑張って整備しなくても条件によっては問題なさそうです。

[^1]: 料金はボリュームディスカウントあり。https://cloud.google.com/maps-platform/pricing/sheet/?hl=ja

３はちょっとコストが高い（1,000回のマップ描画で７ドル[^1]）が、プレイスの手元データや
サイトのレイアウトと連携するためにはこちらを選択することになりそうです。
なおマップ描画は
new google.maps.Map()；
の実行で発生するので、1回の描画を使いまわせる画面遷移にしないとコストで死にそうです。


それぞれの対応ドキュメントはこちら
https://developers.google.com/maps/documentation/urls/guide
https://developers.google.com/maps/documentation/maps-static/intro
https://developers.google.com/maps/documentation/javascript/tutorial
##拠点までの案内をする
現状は埋め込み一択だと思います。なので道案内と複数拠点の一覧化は両立できない感じです。

東京駅から大阪駅まで公共交通機関
https://www.google.com/maps/dir/?api=1&origin=東京駅&destination=大阪駅&travelmode=transit
詳細はドキュメントのMap Actions > directions参照

Dynamic Mapを利用するようなパターンとしては
・地方で車しか使わない
・複数の拠点を巡回するルートマップを表示したい
などでしょうか。

##拠点をピンで一覧化する
Static APIかJavascript APIを使うことになります。
ただStatic APIは返ってくるのが画像なので、それぞれの拠点に関する詳細情報を
インタラクティブに表示するという場合は向きません。

とにかく拠点が地図上の位置関係で分かればOKという場合は安価なStatic APIでStatic Map
マップを操作して拠点情報を確認できるようにしたい場合はJavascript APIでDynamic Map。

ピンは緯度経度指定立てることになるので、もし手元にあるデータが住所だけの場合
geocoding apiまたはplace apiを使って取得します。

ただし、geocoding apiで1,000リクエストあたり５ドル[^1]、
place apiでは1,000リクエストあたり１７ドル[^1]かかるので、
住所データベースに緯度経度をセットで持つ前提で設計した方が良さそうです。

#現在地を利用する
googleのドキュメントでも現在はHTML5標準装備の
navigator.geolocationを利用しています。
https://google-developers.appspot.com/maps/documentation/javascript/examples/map-geolocation?hl=ja

Javascript APIを利用する場合は、new google.map.Mapで描画したあとMapインスタンスの
setCenter()を呼び出して地図の中心を現在地に合わせることも可能です。

Maps URLsやStatic APIの場合は先に座標を取得してリクエスト。

経路案内に利用する場合
東京駅から大阪駅まで公共交通機関（緯度経度版）
https://www.google.com/maps/dir/?api=1&origin=35.6812362,139.7649361&destination=大阪駅&travelmode=transit

#ピンをクリックされたら地点情報を表示する
データを手元に持つ場合とgoogle mapから取得する場合で若干手順が変わりますが
基本的にはDynamic Mapにnew google.map.Marker()でインスタンスを生成して
MarkerインスタンスからaddListenerを呼び出して
インスタンスにバインドした緯度経度を拾う処理を実行する流れになるかと思います。

##データが手元にある場合
###情報を表示するDOMが固定位置の場合
addListenerで設定したリスナを使い、インスタンスから緯度経度を取得します。
緯度経度をキーにして手元データを検索し、サイト上に表示してあげれば良いと思います。
###情報をピンの近くに表示する場合
new google.maps.InfoWindow()でInfoWindowインスタンスを生成し、
これをMarkerインスタンスのクリックイベントにバインドします。
https://developers.google.com/maps/documentation/javascript/infowindows

##google mapからデータを取得する場合
基本的な情報はplace APIのfindplacefromtextを利用して取得できます。
住所をキーにして東京タワーの基本的な情報を取得する場合の一例
https://maps.googleapis.com/maps/api/place/findplacefromtext/json?key=[your_api_key]&input=東京都港区芝公園４丁目２−８&inputtype=textquery&language=ja&fields=formatted_address,icon,name,photos,place_id,plus_code,types,opening_hours,geometry

これで十分なデータが取得できていれば後は手元にある場合と同様です。

##googleから地点の写真を複数取得したい場合

私の場合、写真のデータを複数取得したいと思ったのですが、
これはplace APIのfindplacefromtextでは取得できません。

この場合はfindplacefromtextで取得したplaceidをキーにしてdetailsを使います。
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJCewJkL2LGGAR3Qmk0vCTGkg&key=[your_api_key]&fields=photo

これで写真のリファレンスが一気に取得できます。このリファレンスを使って

```HTML

<img src="https://maps.googleapis.com/maps/api/place/photo?key=[your_api_key]&photoreference=CmRaAAAAZaf50CutgRpoAYw7vzfRT93oKPW-c_fq6CnI6GaPxN-jnt5LGFKqZ9eZMFlj_n6J7mF6sE2E1qBftaR0Kqmkk4uIVdP5loahySzhRirpBfnIU2D6XQ7X5Eh-mgGZYp3gEhBssaY95AEIv2qv_ArZFCDOGhTzUw5urmxQrag3-qGuyhkeL53nCQ&maxheight=400">
```
このようにimgタグを生成すればOKです。urlが長いですがスクロールして確認してください。

ただ、これについてもplace APIをfindplacefromtext, details, photoと3回も使うので
非常にコストがかかります。
findplacefromtext : 17ドル[^1]/1,000リクエスト
details : 17ドル[^1]/1,000リクエスト
photo : ５ドル[^1]/1,000リクエスト

こうなると、定期のバッチ処理で画像urlを取得して手元に置いておくのが良さそうです。
#終わりに
用意されているAPIが多いのでちょっと得体が知れない感がありますが
整理してみると扱い自体は簡単です。

あとは、UI設計側、インフラ側、運用側とも協力して
＊なるべくURLsで済ませる
＊自前データを整備するかバッチで手元に取り込む
ことでコストを抑えていく工夫は結構大事かも知れませんね。