LoginSignup
1
2

More than 3 years have passed since last update.

Google Mapをウェブサイトに埋め込む方法

Posted at

Twitterのように、投稿する情報に自分がいる位置を付け加えて、投稿詳細画面を開くと、埋め込んだGoogle Mapがでてくるようにしました。

1. データベース設計

今回は投稿する情報に位置情報を乗せてあげたかったので、postsテーブルにlatitude(緯度), longitude(経度)を設計しました。integerで設定してしまうと、小数点以下が切り捨てられてしまうため、データ型はfloat(浮動小数点型)にしています。
また、位置情報を乗せたくない人もいるでしょうから、validationは切っておきました。

column_name type option
text string -
user_id integer -
latitude float -
longitude float -
created_at datetime null: false
updated_at datetime null: false

2. 今回使ったGem

どうしても、データベースからデータを引っ張って、Javaに渡す方法がわからなかったので、以下のGemを使用しました。
他にいい手段があればご指摘ください。

Gemfile
gem 'gon'
#Railsのコントローラー側で生成したインスタンス変数を、Javaのファイルの中で使用することができる。

3. controllerの設定

コントローラー側では、showアクションでgooglemapを表示したいので、gon.postに@postインスタンスを代入する。

posts_controller.rb
class PostsController < ApplicationController

  def show
    @post = Post.find(params[:id])
    gon.post = @post #gonを頭に持ってくることで、postインスタンスをJavaScriptsのファイル上でgon.postとして使用可能になる
  end

  def update
    @post = Post.find(params[:id])
    @post.update(post_params)
    redirect_to root_path
  end

  private

  def post_params
    params.require(:post).permit(:text, :user_id, :latitude, :longitude).merge(user_id: current_user.id)
  end

end

4. htmlとcssファイル設定

application.html.erbファイルのheadタグの中に以下を記述。

:application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>MapApp</title>
    #省略
    <%= include_gon %>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=ここにGoogleAPIの認証キーを記述&callback=initMap" type="text/javascript"></script>
    <%= javascript_include_tag "map.js" %>
  </head>
  <body>
  #省略
  </body>
</html>
<%= include_gon %>
gemで設定した、gonを使えるようにする。

<script async defer src="https://maps.googleapis 以下略>
Google Mapを埋め込み利用するために、GoogleAPIの鍵を取得して、key=以下にコピペしてください。
注意:GitHubにアップロードするときは、公開用の鍵を設定しないと悪用される可能性があります。

<%= javascript_include_tag "map.js" %>
map.jsファイルに今回のJavaScriptsの記述をまとめましたので、ここでローディング。

入力フォームに現在位置を自動入力して、消えるボタンを設置します。

post.hemlt.erb
<button id="button" onclick="getPosition()">位置情報を有効にする</button><br>
#"位置情報を有効にする"ボタンをクリックすると、map.jsのgetPosition()メソッドが動き、現在位置の緯度と経度をしたのlatitude, longitudeフォームに自動入力してくれるようにしました。
<p id="getPosition"></p>
<%= form_for(@post, url: "/posts/#{@post.id if @post}") do |f| %>
  <%= f.label "Text" %>
  <%= f.text_field :text, placeholder: "input text" %><br>

  <%= f.label "latitude" %>
  <%= f.text_field :latitude, placeholder: "input latitude", id: "latitude" %><br>

  <%= f.label "longitude" %>
  <%= f.text_field :longitude, placeholder: "input longitude", id: "longitude" %><br>
  #緯度と経度の入力フォームは、上記のボタンを押せば自動で記入してくれますが、ここではほかの場所のmapも取得したかったので、あえてフォームを表示しました。また、ボタンを一度押したら、消えるようにしています。
  <% if @post.text %>
    <%= f.submit "Update", method: :patch %>    
  <% else %>
    <%= f.submit "Submit", method: :post %>
  <% end %>
<% end %>

投稿詳細では地図が実際に表示されるように、ボタンを設置。

show.html.erb
<%= @post.user.name %><br>
<%= @post.text %><br>
<%= @post.latitude %><br>
<%= @post.longitude %><br>
<%= @post.created_at %><br>
<% if @post.latitude && @post.longitude  %>
  <button id="button" onclick="showGoogleMap()">投稿した位置を表示する</button><br>
  #"投稿した位置を表示するボタンをクリックすると、map.jsのshowGoogleMap()メソッドが動き、下の<div id="sample">の中にgoogle mapが表示されるようになります。また、このボタンが消えるようにしました。
    <% if user_signed_in? && @post.user_id == current_user.id %>
      <div>
        <%= link_to "EDIT", "/posts/#{@post.id}/edit" %>
        <%= link_to "DELETE", "/posts/#{@post.id}", method: :delete %> 
      </div>
    <% end %>
  <div id="sample"></div>
  #ここに地図を表示
<% end %>

google mapを埋め込むにあたりcssでサイズを設定しなければ、表示されないので、divの箱のサイズを設定しておきます。

posts.scss
#sample {
  width: 700px;
    height: 400px;
 }

5. map.jsの記述

最初に現在位置を取得する、プログラムを記述

map.js
function getPosition() {
  var x = document.getElementById("getPosition"); #ブラウザが対応しているか結果表示用
  var b = document.getElementById("button"); #ボタンを消す用
  var lat = document.getElementById("latitude"); #緯度をlatitude_formに記入する
  var lon = document.getElementById("longitude"); #緯度をlongitude_formに記入する
  #htmlの中からそれぞれのidを持つ要素を取得

  function getLocation() {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(showPosition);
      #geolocationAPIがサポートする現在位置を取得するメソッド引数にコールバック関数として後述のshowPosition関数を記述してそこにpositionオブジェクトを返す
  } else {
      x.innerHTML = "Geolocation is not supported by this browser.";
      #ブラウザが対応してなければサポートしていないと返す
    }
  }
  getLocation() #実行
  function showPosition(position) {
    lat.value = position.coords.latitude; #positionオブジェクトから緯度を取得
    lon.value = position.coords.longitude; #positionオブジェクトから経度を取得
  }
  b.style.display = "none"; #ボタンを消す
}
#getLocation()の返り値にpositionが返されそれをそのままshowPositionに使用すると現在位置情報が取得できる

これで投稿時に緯度と経度が入力できました。

map.js
function showGoogleMap(){
  var map; #google map表示用
  var marker; #google mapに現在位置のピンを留める
  var b = document.getElementById("button"); #ボタンを消すため
  var center = {
    lat: gon.post.latitude,
    lng: gon.post.longitude
  };
  #google mapのセンターを現在位置にするshowコントローラーを呼び出すためここでgon.postを使って投稿した時の現在位置を呼び出す

  function initgoogleMap(){
    map = new google.maps.Map(document.getElementById('sample'),{
      center: center,
      zoom: 17
    });
    marker = new google.maps.Marker({
      position: center,
      map: map
    });
  }
  initgoogleMap()
  b.style.display = "none";
}

以上で、最低限Google Mapを表示することができるようになりました。Geolocationをもっと勉強すれば、より理解度が深まりそうな気がします。

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