12
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Google Maps APIで観光地、施設名等から住所を表示する

Last updated at Posted at 2020-05-01

GoogleMapで地名や施設名から緯度、経度を表示できるようにする方法はいくつか見つけましたが、住所を表示できるようにする方法がなかなか見つからなかったので、自分なりに解決した方法をまとめておきます。

#作成するアプリ

f2df81a4220d468932c0f0ff70ca5b0d.gif

#実装内容
フォームに入力した情報から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つのファイルを編集します。

##ルーティング

routes.rb
Rails.application.routes.draw do
  get 'maps/index'
  root to: 'maps#index'
  resources :maps, only: [:index]
end

##コントローラー

maps_controller.rb
class MapsController < ApplicationController
  def index
  end
end

ルーティング、コントローラーはこれで完成です。

#ビューの作成
ビューは記述する内容が多いので段階を踏んで書きます。
・HTMLの作成
・GoogleMapの表示
・入力した情報によるGoogleMapの表示変更
・緯度経度、住所の表示

##HTMLの作成
まずは土台になるHTMLから編集していきます。

index.html.erb
<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>

以下のように表示できたら成功です。
スクリーンショット 2020-04-30 16.22.23.png

ここでは<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引数に指定されているオプションcenterzoompositionmapは必ず設定が必要なので忘れずに設定しましょう。

今回は東京の座標を設定していますが、別の座標でも構いません。

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>

最後の行のYOUR_API_KEYには自分で取得したAPIキーを入れてください。

ここまで実装したら以下のように表示できるか確認しましょう。
表示できたら成功です。

スクリーンショット 2020-04-30 16.15.00.png

##入力した情報による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を利用してmapmarkerを設定していきます。

ここではmapのsetCenterというメソッドを利用してmapの座標を設定します。
setCenterを利用するためには緯度経度の値が必要になります。
resultsの中にある緯度経度の値はresults[0].geometry.locationというコードで取得できるので取得して座標を設定します。

markerを設定する方法はGoogleMapの表示のときに説明しているので割愛します。

それではどのようになっているか確認しましょう。
以下のように表示できたら成功です。

2c89d8c173218b0f755034b68ba7ab65.gif

##緯度経度、住所の表示

最後に緯度経度、住所を表示できるようにしていきます。
以下のコードを追加します。

//ここから追加
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_addressresultsの中から住所の値を取得するために必要なコードになります。
取得しましたら、先ほどと同じようにinnerHTMLでHTMLにresults[0].formatted_addressの値を表示させましょう。

それでは動作確認してみましょう。
以下のように表示できたら完成です。
お疲れ様でした。

211baaf0c41c2dd54917ce93c3ab7961.gif

#追記(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

12
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?