Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@mousphere

動的にGoogle Mapを複数表示する機能を実装しました

作成した記事内に住所が記載されている場合には、その住所にピンを立てて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() {
  //処理内容
});

終わりに

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What is going on with this article?