LoginSignup
7
7

【Rails】Google mapのマーカー(ピン)をカスタマイズして遊んでみた

Posted at

はじめに

こんにちは。kosukein38です。
最近仕事でGoogle map API(Maps JavaScript API)を使っていました。
後学も兼ねて、マーカー(ピン📍)を色々カスタマイズして遊んでみました🥳
自分は"ピン"を立てるとかってよくいうのですが、公式に習って、本記事では"マーカー"と呼ぶことにします。
徐々にステップアップする感じで書いてみたので、良かったら参考にしていただけたら幸いです。

この記事の対象者

  • Google map API(Maps JavaScript API)を初めて触る方
  • RailsアプリにGoogle mapを組み込んで、あれこれ情報を表示したい方

内容(この記事でやること、やらないこと)

やること

  • Google map API(Maps JavaScript API)をRailsに導入する
  • 地図を描画する
  • 地図にマーカーを立てる
  • マーカーの見た目を変える
  • マーカーに吹き出しをつける + マーカークリックで吹き出しを表示する
  • 【ちょっと応用】複数のマーカーを設置、その属性値で吹き出しやHTMLを書き換える

やらないこと

  • Rails側の設定やAPIの設定の詳細
    • 詳しい設定方法は書いていません、Googleの公式ドキュメントや、またasset周り設定方法は公式ドキュメント、Railsガイドを参照してください。

本題

Google map API(Maps JavaScript API)をRailsに導入する

まずは以下の公式ドキュメントを参照ください。
以下の公式ドキュメントを参考にしてください

Maps JavaScript API を読み込む  |  Google for Developers

以下の 3 つの方法で読み込むことができます。

ちょっと古い方法のようですが、今回は3つめのスクリプト読み込みタグを利用します。

以下のタグをGoogle Mapを読み込ませたいビューに配置します。

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

APIキーは秘匿情報に当たるので、.envCredentialsで管理してください。
自分はRails4.2を使って(古いのは承知の上ですw)テストしましたので、以下のようなビューを作りました。

app/views/test.html.erb
<div class="mt10" id='custom-map'></div>
<div id='text'>
  <h1>テスト文字列</h1>
</div>

<%= javascript_include_tag 'test' %>
<%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?key=#{ENV['API_KEY']}&libraries=places&callback=initMap" %>

ビューを表示できるように、適当にコントローラーとルーティングを設定します。(詳細は省略)
今回はtest.jsファイルにJavaScriptを書いて、操作していきます。

地図を描画する

Maps JavaScript API を読み込む  |  Google for Developers

initMap()関数でGoogleMapを描画します。

app/assets/javascripts/test.js
let map;

function initMap() {
  map = new google.maps.Map(document.getElementById("custom-map"), {
    center: { lat: 35.658581, lng: 139.745433 },
    zoom: 12,
  });
}

window.initMap = initMap;


結果はこんな感じです。簡単に地図が表示できますね。(For development purposes onlyは気にせず...w)

スクリーンショット 2023-11-23 23.42.06.png

地図にマーカーを立てる

マーカー  |  Maps JavaScript API  |  Google for Developers

実際にマーカーを立てていきますmarker = new google.maps.Marker()でマーカーのインスタンスを作成します。

app/assets/javascripts/test.js
let map;

function initMap() {
  const position = { lat: 35.658581, lng: 139.745433 };
  map = new google.maps.Map(document.getElementById("custom-map"), {
    center: { lat: 35.658581, lng: 139.745433 },
    zoom: 8,
  });

  marker = new google.maps.Marker({
    position: position,
    map: map,
    title: "tokyo-tower",
  });
}

window.initMap = initMap;

結果はこんな感じ、見慣れたマーカー📍が立ちました。

スクリーンショット 2023-11-23 23.45.09.png

マーカーの見た目を変える

Google マップのカスタマイズ: カスタムのマーカー  |  Maps JavaScript API  |  Google for Developers

マーカーがデフォルトのままでは寂しいのでちょっと変えてみましょう。
例えばRailsではpublic/img/map_logo.pngといったように、マーカーにしたい画像ファイルを配置してみます。
↓こんな画像
map_logo.png

app/assets/javascripts/test.js
let map;

function initMap() {
  const position = { lat: 35.658581, lng: 139.745433 };
  map = new google.maps.Map(document.getElementById("custom-map"), {
    center: { lat: 35.658581, lng: 139.745433 },
    zoom: 8,
  });
  
  marker = new google.maps.Marker({
    position: position,
    map: map,
    title: "tokyo-tower",
  });

  marker.setOptions({
    icon: { 
      url: '/img/map_logo.png'
    }
  });
}

window.initMap = initMap;

結果はこんな感じ、マーカーに色がつきました!

スクリーンショット 2023-11-23 23.50.26.png

マーカーに吹き出しをつける + マーカークリックで吹き出しを表示する

情報ウィンドウ  |  Maps JavaScript API  |  Google for Developers

さらにレベルアップして、マーカーをクリックすると、情報ウィンドウ(吹き出し)が出てくるようにしてみましょう。

app/assets/javascripts/test.js
let map;

function initMap() {
  const position = { lat: 35.658581, lng: 139.745433 };
  const contentString =
  '<div class="ks_pin">'
  + '<div class="mb5"><a href="'
  + 'https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC'
  + '" class="btn btn-sm btn-default mb5"'
  + '>'
  + 'wikipediaを見る'
  + '</a></div>'
  + '</div>';

  const infowindow = new google.maps.InfoWindow({
    content: contentString,
  });

  map = new google.maps.Map(document.getElementById("custom-map"), {
    center: { lat: 35.658581, lng: 139.745433 },
    zoom: 12,
  });

  marker = new google.maps.Marker({
    position: position,
    map: map,
    title: "tokyo-tower",
  });

  marker.setOptions({
    icon: { 
      url: '/img/map_logo.png'
    }
  });

  marker.addListener("click", () => {
    infowindow.open({
      anchor: marker,
      map,
    });
  });
}

window.initMap = initMap;

結果はこんな感じ、簡単に吹き出しを出すことができます。

9d6496d5870a7917a66096f7ecddc9f3.gif

【ちょっと応用】複数のマーカーを設置、その属性値で吹き出しやHTMLを書き換える

最後にちょっと応用編ということで、2つのマーカーを設置して、その属性値を利用して吹き出しの内容や、ビューのHTMLを書き換えるようなことをやってみます。

app/assets/javascripts/test.js
let map;
let marker = [];
let infoWindow = [];
let previous_i;

// マーカーにクリックイベントを付与
function markerEvent(i) {
  marker[i].addListener('click', function() {
    let markerTitle = marker[i].title;
    toggleText(markerTitle);
    // 前のピンをクリックしたら吹き出しをクローズする処理
    if (previous_i !== undefined) {
      infoWindow[previous_i].close(map, marker[previous_i]);
    }
    infoWindow[i].open({
      anchor: marker[i],
      map,
    });
    previous_i = i
  });
}

// マーカーに付与する吹き出しの詳細
function windowDetail(obj) {
  if (obj.title === "tokyo-tower") {
    return '<div>'
    + '<div class="mb5"><a href="'
    + 'https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC'
    + '" class="btn btn-sm btn-default mb5"'
    + '>'
    + 'wikipediaを見る'
    + '</a></div>'
    + '</div>';
  } else if (obj.title === "sky-tree") {
    return '<div>'
    + '<div class="mb5"><a href="'
    + 'https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E3%82%B9%E3%82%AB%E3%82%A4%E3%83%84%E3%83%AA%E3%83%BC'
    + '" class="btn btn-sm btn-default mb5"'
    + '>'
    + 'wikipediaを見る'
    + '</a></div>'
    + '</div>';
  }
}

// マーカーのタイトル属性でテキストを書き換える
function toggleText(title) {
  let h1Element = document.querySelector('#text h1');
  if (title === "tokyo-tower") {
    h1Element.innerHTML = "東京タワーですよ!";
  } else if (title === "sky-tree") {
    h1Element.innerHTML = "スカイツリーですよ!";
  }
}

// 複数のデータを受け取ってマーカーを設置する
function setMarkers(data) {
  for (var i = 0; i < data.length; i++) {
    // マーカーを立てる
    position = {lat: parseFloat(data[i]['lat']), lng: parseFloat(data[i]['lng'])};
    markerLatLng = new google.maps.LatLng(position);
    marker[i] = new google.maps.Marker({
      position: markerLatLng,
      map: map,
      title: data[i]['title'],
    });
    // マーカーのアイコンを変える
    marker[i].setOptions({
      icon: { 
        url: '/img/map_logo.png'
      }
    });
    // マーカーに吹き出しセット
    infoWindow[i] = new google.maps.InfoWindow({
      content: windowDetail(data[i])
    });
    // マーカーにクリックイベントセット
    markerEvent(i);
  }
}

// 地図の描画処理
function initMap() {
  data =[
    {
      title: "tokyo-tower",
      lat: "35.65871123089065",
      lng: "139.74537925206033",
    },
    {
      title: "sky-tree",
      lat: "35.71292005728178",
      lng: "139.81072185646673",
    },
  ]

  map = new google.maps.Map(document.getElementById("custom-map"), {
    center: { lat: 35.658581, lng: 139.745433 },
    zoom: 12,
  });

  setMarkers(data);
}

// initMap関数の呼び出し
window.initMap = initMap;

結果はこんな感じ。あなたは東京タワー派ですか?スカイツリー派ですか??

a1b998f83557b3537b6df1ebd95f88d8.gif

まとめ

  • 最後の例を応用すると、例えば、RailsバックエンドのAPI経由でDBのデータをJSONで取得して、そのデータ配列からピンを生成するみたいなこともできますね。
  • GoogleMap APIは色んなプロダクトでよく使われるAPIだと思いますので、参考にしていただけたら幸いです。
  • 本記事で紹介したコードで、非推奨のメソッドなどが今後出てくる可能性もありますので、最新情報は必ず公式ドキュメントで確認してください。
  • 最後まで読んでいただきありがとうございました。

参考

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