0
1

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 Mapを複数表示する機能を実装しました

Last updated at Posted at 2020-04-25

作成した記事内に住所が記載されている場合には、その住所にピンを立ててGoogleMapを表示する機能を実装しました。
ページ内でいくつのGoogle Mapが表示されるかわからないので動的に対応できる必要があります。

#前提

  • Google Maps Javascript APIを使用できる状態にある

#環境
Ruby 2.6.3
Rails 5.1.7

#実際のコード

_article.html.erb
<li id="article-<%= article.id %>">
  <% if article.address.present? %>
    <div>
      <span>
        住所:<span id="address-<%= article.id %>"><%= article.address %></span>
      </span>
    </div>
    <div id='map-<%= article.id %>'>
    </div>
    <script>
      $(document).on('turbolinks:load', function() {
        const geocoder = new google.maps.Geocoder();

        const map = new google.maps.Map(document.getElementById('map-<%= article.id %>'), {
          center: {lat: -34.397, lng: 150.644}, //任意の値
          zoom: 12 //任意の値
        });

        const inputAddress = document.getElementById('address-<%= article.id %>').textContent;

        geocoder.geocode( { 'address': inputAddress}, function(results, status) {
          if (status == 'OK') {
            map.setCenter(results[0].geometry.location);

            const marker = new google.maps.Marker({
              map: map,
              position: results[0].geometry.location
            });
          } else {
            alert('Geocode was not successful for the following reason: ' + status);
          }
        });
      });
    </script>
  <% end %>
</li>
application.css.scss
div[id^="map-"]{
    height: 300px; //任意の値
}
application.html.erb
<html>
  <head>
  ...
  </head>
  <body>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
    <%= yield %>
  </body>
</html>

#ポイント
##1. Google Mapや住所に一意のidを割り当てる
・_article.html.erb 8行目

<div id='map-<%= article.id %>'>

各Mapに一意のidを割り当てるために、記事のidを付随させました。
そしてそのidに対応するMapを作成します。

・_article.html.erb 14〜17行目

const map = new google.maps.Map(document.getElementById('map-<%= article.id %>'), {
  center: {lat: -34.397, lng: 150.644}, //任意の値
  zoom: 12 //任意の値
});

同様に、記事の住所にも一意のidを付与し、その文字列を取得できるようにしています。

また、それらのidに対してそれぞれstyle(heightやwidth等)を適用させる必要があります。
調べてみると、cssでは前方一致等、簡単な正規表現が使用できるそうなので以下の設定としました。

application.css.scss
div[id^="map-"]{
    height: 300px; //任意の値
}

id^="map-" とすることで、"map-"から始まる任意のid(例:map-1, map-hoge等)が付与されたdivタグに対しstyleを適用できます。

参考:
CSSでセレクターに正規表現を使うには?コード例で解説

##2. GoogleMapsAPIを使用するためのスクリプトをMap生成コードより手前に置く
・application.html.erb 5〜8行目

<body>
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
  <%= yield %>
</body>

ページ内で表示させるMapが1つである場合等は、scriptのsrcにコールバック関数を指定して実行するのが一般的なようです。
その場合はMapsAPIを使用するためのスクリプトをMap生成コードの下に置くことになると思いますが、今回のように、ある条件下ではMapが生成されるような、動的に表示数が変化する場合は1つのコールバック関数では対応できないのでMap生成コードより手前で、あらかじめGoogleMapsAPIを使用できる状態にしておきます。

##3. ページ読み込み時にMap生成を実行する
コールバック関数は使わないので、代わりに以下関数でページが読み込まれたら(turbolinksがロードされたら)即実行されるようにします。

$(document).on('turbolinks:load', function() {
  //処理内容
});

#終わりに
最後までお読みくださりありがとうございました。
どなたかの参考になれば幸いです。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?