RailsでGoogle Mapsを扱うときのライブラリを公開しました

Shunsuke Sawada

ウェブサービス作っていてGoogle Mapsを使うことって凄く多い。
個人的に旅とか海外とかのサービスが多いだけなのかもしれないけど。

coffee scriptのファイルをプロジェクト毎に作っていたけど、結局同じコードなのでGithubに公開しておきました。

rails-googlemaps
  
レポジトリはこちら
shunwitter/map_helper

デモはこちら(定期的に消えるので地図登録してOKです)
https://shunwitter-test-app.herokuapp.com/places

実際のプロジェクトではこんな感じ
http://www.canpath.jp/ (ページ最下部のマップとか)

  
できることは、

以下 Github とほぼ同じですが日本語で。
jQueryが必要です。

読み込み

vendorフォルダに置いたファイルを読み込む。
ここに置きました。

vendor/javascripts/map_helper/maphelper.coffee

/app/assets/javascripts/application.js

1
//= require map_helper/map_helper

Railsアプリ

この例では、Place model があると想定します。
scaffoldでつくるとこんな感じですね。

1
rails g scaffold place name:string address:stiring latitude:float longitude:float

  
RailsのTurbolinksを使っている場合はこんな感じでGoogle maps apiを読み込むかと思います。
triggerMapでこのライブラリを使うコードを書いていきます。

/app/assets/javascripts/places.js.coffee

coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ready = ->

  if !window.google

    script = document.createElement('script')
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&' +
                  'language=ja&callback=triggerMap'
    document.body.appendChild(script)

  else
    triggerMap()

window.triggerMap = ->
  # your code

# For turbolinks
$(document).ready(ready)
$(document).on 'page:load', ready

  

1. マップを表示する

マップを表示するdiv要素に data-latitudedata-longitude を設定してください。

View

app/views/places/show.html.erb

erb
1
2
3
4
5
6
<div class="map-show-canvas" 
            data-latitude="<%= @place.latitude %>"
            data-longitude="<%= @place.longitude %>">
</div>

Javascript

MapHelper.showMap(canvas, options)

/app/assets/javascripts/places.js.coffee

coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
window.triggerMap = ->

  # --- show --- #
  mapCanvas = $('.map-show-canvas')
  if mapCanvas.length && mapCanvas.attr('data-latitude')

    MapHelper.showMap(mapCanvas.get(0),
      {
        mapHeight:      300,
        mapLat:         mapCanvas.attr('data-latitude'),
        mapLng:         mapCanvas.attr('data-longitude'),
        zoom:           10
        #scaleControl: ,
        #scrollwheel: ,
        #showMarker: ,
        #draggable: ,
      }
    )

Options

Name Type Default
mapHeight integer 300
mapLat float 35.6894875 #Tokyo
mapLng float 139.6917064 #Tokyo
zoom integer 4
scaleControl boolean true
scrollwheel boolean false
showMarker boolean true
draggable boolean false
afterShow function null

  
  

2. 検索ボタンをしたらマップ表示

DEMOです。

検索ボタンがされたら、
住所から位置を特定してマップを表示 & 緯度経度フィールドに値をセットする。

addressInput で指定された要素を全部合わせた住所で検索するので複数になってもOKです。
例えば、

| address | state | postcode |

みたいになっていれば、それぞれに同じクラス名をつけることで
address + state + postcode みたいな文字列を Google maps api に投げます。

View

app/views/places/new.html.erb

erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%= form_for(@place) do |f| %>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :address %><br>
    <%= f.text_field :address, class: "address" %>
    <%= link_to "SEARCH", "#", class: "map-search-button" %>
    <div class="map-canvas" style="height: 0;"
                data-lat="<%= f.object.latitude %>"
                data-lng="<%= f.object.longitude %>">
    </div>
    <%= f.text_field :latitude, readonly: true %>
    <%= f.text_field :longitude,readonly: true %>
  </div>
<% end %>

Javascript

MapHelper.searchShowMap(canvas, options)

coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
window.triggerMap = ->

  # --- new/edit --- #
  if $('.map-search-button').length

    MapHelper.searchShowMap($('.map-canvas').get(0),
      {
        mapHeight:      300,
        trigger:        $('.map-search-button'),
        addressInput:   $('.address'), #could be multiple
        latInput:       $('#place_latitude'),
        lngInput:       $('#place_longitude'),
        zoom:           10
        #scaleControl: ,
        #scrollwheel: ,
        #showMarker: ,
        #draggable: ,
        afterShow: -> 
          console.log "Map is displayed."
      }
    )

Options

Name Type Default
mapHeight integer 300
trigger jQuery object $('.search-map-trigger')
addressInput jQuery object $('.search-map-address')
latInput jQuery object $('input.latitude')
lngInput jQuery object $('input.longitude')
zoom integer 4
scaleControl boolean true
scrollwheel boolean false
showMarker boolean true
draggable boolean false
afterShow function null

  
  

3. マップ表示とたくさんマーカー表示

マーカーを地図上に沢山表示する時に便利です。
jsonを受け取りますので、コントローラー側の設定もしてください。

Controller

/app/controllers/places_controller.rb

ruby
1
2
3
4
5
6
7
8
9
def index
  @places = Place.all
  respond_to do |f|
    f.html
    f.json { render json: @places }
  end
end

View

app/views/places/index.html.erb

erb
1
2
3
<div class="map-index"></div>

Javascript

MapHelper.showMapWithMarkers(canvas, options, json)

coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
window.triggerMap = ->

  # --- index --- #
  if $('.map-index').length
    $.ajax(
      type: 'GET',
      url: '/places.json',
      # data: { if you need }
    ).done( (data) ->
      if data.length
        MapHelper.showMapWithMarkers($('.map-index').get(0),
          {
            mapHeight:    400,
            mapLat:       data[0].latitude,  #center
            mapLng:       data[0].longitude, #center
            zoom:         2,
            showMarker:   false,
            draggable:    false,
            controller:   'places',
            titleField:   'name'
          }, data)
    )

Options

controller and titleField は表示されたマーカーをクリックした時にでるウインドウのために使用されます。
Placeモデルにnameというフィールドがあったら titleField: 'name' としてください。
タイトルには /controller/:id みたいなリンクが貼られます。

ウインドウとはコチラのことです。

Name Type Default
mapHeight integer 300
mapLat float 35.6894875 #Tokyo
mapLng float 139.6917064 #Tokyo
zoom integer 4
scaleControl boolean true
scrollwheel boolean false
showMarker boolean true
draggable boolean false
afterShow function null
controller string "posts"
titleField string "title"

いろいろ変えたい

ホントは Gem化してみたりしたかったけど、
やり方を覚えるのに時間かかりそうなので後日。

また、Javascriptファイルでもなく、Coffee script のままという何とも乱暴な感じです。

jQuery なんて必要ないじゃないかとか色々突っ込みどころはありますが、
ひとまず公開してしまいました。
  

101
Shunsuke Sawada

おすすめの記事

webpackを使ってJSとCSSをコンパイルする(ES6 / Sass)
Turbolinks で Google adsense が正しく表示されない時の対処方法
5
RailsでGoogle mapsを使いこなすためのメモ 2 / 地図デザインのカスタマイズ
2