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

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

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

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

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

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

  
できることは、

  • 1. 緯度経度を受け取ってマップ表示
  • 2. 住所を入力してボタンを押したら、マップ表示&緯度経度セット
  • 3. マップ表示 + たくさんのマーカー表示

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

読み込み

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

vendor/javascripts/map_helper/maphelper.coffee

/app/assets/javascripts/application.js

//= require map_helper/map_helper

Railsアプリ

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

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

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

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


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


<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


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

<%= 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)


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


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


<div class="map-index"></div>

Javascript

MapHelper.showMapWithMarkers(canvas, options, json)


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 なんて必要ないじゃないかとか色々突っ込みどころはありますが、
ひとまず公開してしまいました。
  

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた