[Rails7.0] GoogleMapの地図上のピンをクリックすると発火するイベントをHotwireで拾う

2023/06/10

GoogleMap
Rails

こんにちは。

Google Map APIを使って地図上のピンをクリックすると発火するイベントをHotwireで拾う方法を紹介します。

イメージが掴みにくいと思うので、まずは完成形を見てみましょう。

https://www.value-hoiku.jp/recruitments/map

このような形で、地図上のピンをクリックすると、ピンに紐づく情報を表示するような仕組みです。

1. Google Map APIの準備

まずは、Google Map APIを使えるようにします。

Google Map APIの使い方は、こちらの記事を参考にしてください。

上記の記事では、Google Map APIのAPIキーを環境変数に設定する方法を紹介しています。

2. Map IDの準備

Google Map APIを使うには、Map IDが必要になります。

Map IDは、Google Cloud Platformのコンソールから取得することができます。

以下のURLにアクセスして、Map IDを取得してください。

https://console.cloud.google.com/google/maps-apis/studio/maps

1.png

MapIDが取得できたら、credentialに登録しておきましょう。

以降、Rails.application.credentials.dig(:gcp, :map_id)でMap IDを取得できるものとします。

3. viewファイルの準備

先ほど作成したAPIを使って、viewファイルを作成します。

app/views/addresses/map.html.haml
= javascript_include_tag "https://maps.googleapis.com/maps/api/js?key=#{Rails.application.credentials.dig(:gcp, :maps_platform_api_key)}&callback=initMap&libraries=marker&v=beta", "data-turbo-track": "reload", defer: true
= javascript_include_tag 'map', "data-turbo-track": "reload", defer: true

= hidden_field_tag :lat, @lat || 35.681236
= hidden_field_tag :lng, @lng || 139.767125
= hidden_field_tag :map_id, Rails.application.credentials.dig(:gcp, :map_id)

#map.w-full.h-full

= turbo_frame_tag "modal"

app/javascript/map.js
let map;

function initMap() {
  const lat = document.getElementById("lat").value;
  const lng = document.getElementById("lng").value;
  const mapId = document.getElementById("map_id").value;

  map = new google.maps.Map(document.getElementById("map"), {
    zoom: 12,
    center: new google.maps.LatLng(lat, lng),
    mapId: mapId,
  });

  const fetchJson = async () => {
    const response = await fetch('/api/v1/addresses.json'); // addressの一覧を取得するAPI、lat, lngを含む
    const data = await response.json();
    return data;
  };

  fetchJson().then(data => {
    eqfeed_callback(data);
  });
}

// Loop through the results array and place a marker for each
// set of coordinates.
const eqfeed_callback = function (addresses) {
  const element = document.querySelector('#modal')

  addresses.forEach (function (address) {
    const latLng = new google.maps.LatLng(address.latitude, address.longitude);

    const pinViewBackground = new google.maps.marker.PinView({
      scale: 1.1,
      glyphColor: "white",
    });

    const marker = new google.maps.marker.AdvancedMarkerView({
      position: latLng,
      map: map,
      title: address.name,
      content: pinViewBackground.element,
    });

    marker.addListener("click", ({ domEvent, latLng }) => {
      const { target } = domEvent;
      element.src = `/addresses/${address.id}`;
    });
  });
};

window.initMap = initMap;
window.eqfeed_callback = eqfeed_callback;

上記で、Google Map APIで表示したピンに対して、クリックイベントを設定しています。
今回はクリックイベントとして、turbo_frame_tagを使って、/addresses/${address.id}を表示するようにしています。

routes.rbやcontroller, viewは各自で作成してください。

今回はこのあたりで。

Related Posts

RailsでGoogle mapの位置情報を扱うモデルを作成する

RailsでGoogle mapの位置情報を扱うモデルを作成する