GoogleMapで地名や施設名から緯度、経度を表示できるようにする方法はいくつか見つけましたが、住所を表示できるようにする方法がなかなか見つからなかったので、自分なりに解決した方法をまとめておきます。
#作成するアプリ
#実装内容
フォームに入力した情報からGoogleMapを更新して、ピンのある場所の緯度経度、住所を表示します。
#実装する前に
Google Maps APIを利用するためには、APIキーを作成する必要があります。
APIキーをまだ作成していない場合は作成してください。
私が参考にした記事があるので、APIキーを作成していない方は参考にしてください。
参考URL
https://qiita.com/nagaseToya/items/e49977efb686ed05eadb
今回私が利用しているAPIライブラリは
・Geocoding API
・Maps JavaScript API
この2つです。
#作成・編集するファイル
・routes.rb
・maps_controller.rb
・index.html.erb
この3つのファイルを編集します。
##ルーティング
Rails.application.routes.draw do
get 'maps/index'
root to: 'maps#index'
resources :maps, only: [:index]
end
##コントローラー
class MapsController < ApplicationController
def index
end
end
ルーティング、コントローラーはこれで完成です。
#ビューの作成
ビューは記述する内容が多いので段階を踏んで書きます。
・HTMLの作成
・GoogleMapの表示
・入力した情報によるGoogleMapの表示変更
・緯度経度、住所の表示
##HTMLの作成
まずは土台になるHTMLから編集していきます。
<h2>Google Map Test</h2>
<input id="address" type="textbox" value="">
<input type="button" value="送信" onclick="codeAddress()">
<div id="latlngDisplay">ここに緯度、経緯が表示される</div>
<div id="addressDisplay">ここに住所が表示される</div>
<div id="map"></div>
<style>
#map{
height: 600px;
width: 600px;
}
</style>
ここでは<style>
タグを使用してマップの大きさを指定していますが、設定しないとGoogleMapが表示されなくなるので必ず指定するようにしましょう。
確認する場合は、<style>
タグの中に下の1文を追加したら確認することができます。
<style>
#map{
height: 600px;
width: 600px;
/* 下の1文を追加 */
background-color: red;
}
</style>
##GoogleMapの表示
次はmap
にGoogleMapが表示されるように編集します。
先ほどのファイルに以下のコードを追加してください。
<style>
/* 省略 */
</style>
<script>
function initMap(){
tokyo = {lat: 35.6803997, lng: 139.7690174}
map = new google.maps.Map(document.getElementById('map'), {
center: tokyo,
zoom: 12,
});
marker = new google.maps.Marker({
position: tokyo,
map: map
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
順に説明していきます。
function initMap(){
//省略
}
intiMap
という関数はGoogle Maps APIの読み込みが完了した後に呼び出される関数なので、変更しないでください。
変更すると動作しなくなります。
//latが緯度、lngが経度を示す
tokyo = {lat: 35.6803997, lng: 139.7690174}
map = new google.maps.Map(document.getElementById('map'), {
//地図の中心になる座標を指定
center: tokyo,
//0~20の間の数値で、表示する地図の大きさを指定
zoom: 12,
});
marker = new google.maps.Marker({
//ピンの表示位置を座標で指定
position: tokyo,
//ピンを表示する地図を指定
map: map
});
new google.maps.Map
はGoogleMapを表示するために、new google.maps.Marker
はGoogleMap上にピンを表示するために必要になります。
それぞれの第2引数に指定されているオプションcenter
、zoom
、position
、map
は必ず設定が必要なので忘れずに設定しましょう。
今回は東京の座標を設定していますが、別の座標でも構いません。
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
最後の行のYOUR_API_KEY
には自分で取得したAPIキーを入れてください。
ここまで実装したら以下のように表示できるか確認しましょう。
表示できたら成功です。
##入力した情報によるGoogleMapの表示変更
ここからは実際にフォームに地名、施設名を入力して、GoogleMapに入力した場所を表示変更できるようにします。
以下のコードを追加します。
funciton initMap(){
//省略
});
}
function codeAddress(){
geocoder = new google.maps.Geocoder();
inputAddress = document.getElementById('address').value;
geocoder.geocode({ 'address': inputAddress}, function(results, status){
if (status == 'OK') {
map.setCenter(results[0].geometry.location);
marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
});
} else {
alert("該当する結果がありませんでした:" + status);
}
});
}
順に説明していきます。
geocoder = new google.maps.Geocoder();
geocoder = new google.maps.Geocoder();
はGeocoding APIを利用するために必要なコードです。
Geocoding APIを利用する場合は必ず書きましょう。
「そもそもGeocoding APIって何をするためのもの?」という人のために簡単に説明しますと、住所を緯度経度に変換したり、緯度経度を住所に変換するために必要なAPIです。
今回のアプリでは住所を緯度経度に変換するパターンと緯度経度を住所に変換するパターンの両方を利用します。
inputAddress = document.getElementById('address').value;
これはフォームに入力した文字列を変数に代入するためのコードです。
value
にはフォームで入力した文字列が入り、その文字列をgeocodeで利用するために変数に代入しています。
geocoder.geocode({ 'address': inputAddress}, function(results, status){
if (status == 'OK') {
//省略
} else {
alert("該当する結果がありませんでした:" + status);
}
});
geocoder.geocode();
はGeocodingにリクエストを送ってレスポンスを受け取るために必要なコードです。
第1引数の{ 'address': inputAddress}
でフォームに入力した文字列をaddress
の形でリクエストします。
address
は地名、施設名、住所などから緯度経度を取得するために必要なオプションです。
第2引数のfunction(results, status)
はレスポンスで受け取った結果を処理するために必要なコールバック関数です。
results
はGeocodingからのレスポンス結果、内容を受け取ります。
status
はGeocodingからのレスポンスステータスコードを受け取ります。
if (status == 'OK') {} else {}
はコールバック関数で受け取ったstatus
がOKだった場合に処理し、それ以外ならelseを処理するというコードです。
map.setCenter(results[0].geometry.location);
marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
});
そしてここからはコールバック関数で受け取ったresults
を利用してmap
、marker
を設定していきます。
ここではmapのsetCenter
というメソッドを利用してmapの座標を設定します。
setCenter
を利用するためには緯度経度の値が必要になります。
results
の中にある緯度経度の値はresults[0].geometry.location
というコードで取得できるので取得して座標を設定します。
markerを設定する方法はGoogleMapの表示のときに説明しているので割愛します。
それではどのようになっているか確認しましょう。
以下のように表示できたら成功です。
##緯度経度、住所の表示
最後に緯度経度、住所を表示できるようにしていきます。
以下のコードを追加します。
//ここから追加
const latlngDis = document.getElementById('latlngDisplay')
const addressDis = document.getElementById('addressDisplay')
//ここまで追加
function initMap(){
//省略
function codeAddress(){
//省略
marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
});
//ここから追加
latlngDis.innerHTML = results[0].geometry.location;
geocoder.geocode({ 'location': marker.getPosition()}, function(results, status) {
if (status == "OK"){
addressDis.innerHTML = results[0].formatted_address;
} else {
alert("Geocode 取得に失敗しました:" + status);
}
});
//ここまで追加
} else {
alert("該当する結果がありませんでした:" + status);
}
});
}
順に説明していきます。
const latlngDis = document.getElementById('latlngDisplay')
const addressDis = document.getElementById('addressDisplay')
まずは、それぞれ緯度経度、住所を表示したい場所のid名を変数で定義します。
latlngDis
が緯度経度を表示する場所、addressDis
が住所を表示する場所です。
latlngDis.innerHTML = results[0].geometry.location;
innerHTML
というプロパティを利用してHTMLのid="latlngDisplay"
に緯度経度の値を持っているresults[0].geometry.location
を表示させます。
これで緯度経度の値を表示することができました。
geocoder.geocode({ 'location': marker.getPosition()}, function(results, status)
先ほどgeocodeを利用した時はaddress
を使いましたが、今回はlocation
を使います。
address
は地名、施設名、住所などからリクエストを送っていましたが、location
は緯度経度からリクエストを送るためのオプションです。
前回は文字列でリクエストを送りましたが、今回は緯度経度でリクエストを送る必要があります。
なので新しく設定したmarkerの緯度経度の値をgetPosition()
というメソッドで取得します。
これで緯度経度の値からリクエストを送ることができます。
addressDis.innerHTML = results[0].formatted_address;
results[0].formatted_address
はresults
の中から住所の値を取得するために必要なコードになります。
取得しましたら、先ほどと同じようにinnerHTML
でHTMLにresults[0].formatted_address
の値を表示させましょう。
それでは動作確認してみましょう。
以下のように表示できたら完成です。
お疲れ様でした。
#追記(2020/05/03)
Geocodeingを利用した住所の表示方法についてですが、
geocoder.geocode({ 'location': marker.getPosition()}, function(results, status) {
if (status == "OK"){
addressDis.innerHTML = results[0].formatted_address;
} else {
alert("Geocode 取得に失敗しました:" + status);
}
});
とコードを書いていましたが、この部分を変更して
addressDis.innerHTML = results[0].formatted_address;
と書いても表示することができました。
私はGeocodingにリクエストを送る方法として
geocoder.geocode({ 'address': inputAddress}, function(results, status)
と書いていましたが、どうやらaddress
でリクエストを送って、レスポンスされたresults
の中に、formatted_address
が取得されているので、location
でリクエストを送る必要はないということが判明しました。
今までは緯度経度と住所の表示にラグがありましたが、これは一つのリクエストで完結しているので、表示にラグがなくなりました。
リクエストを2度送る必要がないので、処理的にもこちらにした方がいいと思います。
#参考にした記事、サイト
https://www.webdesignleaves.com/pr/plugins/googlemap_01.html