[分享] 讓網站支援 Google Map 顯示(圖解)

就如同先前分享過的「切換多語系」功能,這次新添加的「依照工作地點自動生成、顯示 Google Map」依然不是一個 MUST HAVE 功能,但覺得 Google 等大公司的職缺信息都有放一張小地圖,實在太帥了,所以還是硬耗了一天時間折騰。這篇文章濃縮了實裝方式,讓大家少走點冤枉路。如果覺得這篇教程有用,又或是你願意鼓勵支持,歡迎至:我的作品頁面 點下「支持TA」

  • 本篇分享以 Job Listing 教程的代碼作示範,為了節省篇幅,只在 admin/jobs 中添加 Google Map 相關的修改。如果你要在其他頁面顯示,可以照著步驟依樣畫葫蘆。
  • 本篇教程的 GitHub 代碼參考


Step 1. 幫 Job 添加必要欄位(地址、緯度、經度)

在終端機執行:

$ rails g migration add_address_to_job

app/db/migrate 資料夾裡找到剛剛新建的 _add_address_to_job.rb,將內容改為以下:

class AddAddressToJob < ActiveRecord::Migration[5.0]
  def change
    #工作地點
    add_column :jobs, :address, :string  
    
    #需要用到的經緯度欄位
    add_column :jobs, :latitude, :float  
    add_column :jobs, :longitude, :float
  end
end

加好後存檔,在終端機執行:

$ rake db:migrate


Step 2. 管理員在新增工作時可以填入地址

先到在 admin/jobs_controller 修改 def job_params

def job_params
    params.require(:job).permit(:title, :description, :wage_upper_bound, :wage_lower_bound, :contact_email, :is_hidden, :address, :latitude, :longitude)
end

新增、編輯工作的表單記得也要加上「地址」欄位。

  • admin/jobs/new.html.erb
  • admin/jobs/edit.html.erb
<%= f.input :address, :label => t('f_address') %>


Step 3. 安裝 gem 'geocoder',將地址轉換為經緯度

在 Gemfile 中加上 gem 'geocoder',功用是「將『地址』轉換為『經度』、『緯度』,並自動填在欄位 」。

  • Gemfile
# gems for google map

gem 'geocoder'

加好之後存檔,到終端機中執行 bundle install,執行完好請重開 rails server。

為了讓 Geocoder 起作用,我們還必須到 Model 中加上以下兩行代碼;這樣 Geocoder 就會在我們建立或更新工作資訊時,將地址轉換經緯度,然後很貼心地幫我們把資料填入稍早建立的欄位:latitudelongitude

  • app/models/job.rb
# converting address

geocoded_by :address
after_validation :geocode

你可以建一筆有「工作地點」資訊的工作,然後進入終端機 $ rails c 確認。

以此截圖為例,即便我們只填了地址 address: "555 Market Street, San Francisco, CA 94105, USA",這筆工作資料的 latitudelongitude 卻有經緯度的數值。這都是多虧了 Geocoder 這個 Gem 唷!


Step 4. 安裝 gem 'gmaps4rails' 以及 gem 'underscore-rails'

經過上一步,我們有了 Geocoder 幫我們把地址轉成經緯度。我們還需要兩個 Gem 才算是準備就緒。

  • Gemfile
# gems for google map

gem 'gmaps4rails'
gem 'underscore-rails'

加好之後存檔,到終端機中執行 bundle install,執行完好請重開 rails server。

  • app/assets/javascripts/application.js
//= require underscore
//= require gmaps/google


插播:取得 Google Map API Key(API 金鑰)

由於我們要利用 Google 大神的 Google Map API 來顯示地圖,我們必須先取得Google Map API 金鑰

  • 點擊連結,網頁打開後,找到「取得金鑰」

  • 點擊「取得金鑰」後,會跳出一個彈跳視窗。把「Select or create project」的選單點開,選擇選單最下方的「Create a new project」後,原本壓灰無法點擊的「ENABLE API」會變成「CREATE AND ENABLE API」,果斷點擊!

  • 等待一下下,看到這個畫面就萬事 OK 了。「YOUR API KEY」欄位的那一串就是你的「金鑰」,可以先記著等下使用。

Step 5. 顯示 Google Map!

首先,我們要修改 jobs_controller.rb,在 def show 中加入生成地圖的相關代碼(新手如我們就先不追究代碼細節,只要知道代碼的功用是拿 Job 的 latitudelongitude 的經緯度資料產生地圖就好 )。

  • app/controllers/admin/jobs_controller.rb
def show
    @job = Job.find(params[:id])

    # 使用經緯度兩個欄位的數值,建立 Google Map

    @hash = Gmaps4rails.build_markers(@job) do |job, marker|
      marker.lat job.latitude
      marker.lng job.longitude
    end
  end

在 views 中加入以下代碼,「Google Map API 金鑰」這時候就要用上了!請務必記得用剛剛申請的金鑰替換代碼中的「你的API金鑰」。

  • app/views/admin/jobs/show.html.erb
<!-- 測試用,顯示工作地點資訊 -->
<p>緯度:<%= @job.latitude %></p>
<p>經度:<%= @job.longitude %></p>
<p>地址:<%= @job.address %></p>

<!-- 顯示 Google Map -->
<div id="map"></div>

<!-- Google Map 相關代碼 -->
<!-- 請先取得 Google Map API Key(API 金鑰),並用取得的 API 金鑰取代「你的API金鑰」-->
<script src="//maps.google.com/maps/api/js?key=「你的API金鑰」"></script>
<script src="//cdn.rawgit.com/mahnunchik/markerclustererplus/master/dist/markerclusterer.min.js"></script>

<script type="text/javascript">
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
  markers = handler.addMarkers(<%=raw @hash.to_json %>);
  handler.bounds.extendWith(markers);
  handler.fitMapToBounds();
});
</script>

另外,有注意到剛剛貼的代碼中有一行 <div id="map"></div> 嗎?我們還需要到 application.scss 檔設定一下 map 這個 ID 的 CSS 屬性,這一步不單單只是為了頁面的排版,也是為了畫出一個範圍顯示 Google Map (像是準備一塊畫布用來繪製 Google Map);如果沒有設定 widthheight,就無法顯示唷!

  • app/assets/stylesheets/application.scss
// Google Map
#map{
    width:80%; //寬,必須要有!
    height:250px; //高,必須要有!
    margin: 40px;
    margin-left: auto;
    margin-right: auto;
}

以上步驟作完後,回到網頁重整一下,依照該筆工作的「地址」資料生成的 Google Map 就出來了!


Step 6. 解決「使用者必須要刷新頁面,地圖才會顯示」問題

別高興得太早,在測試後,我們發現一個大問題:「使用者必須要刷新頁面,地圖才會顯示」。

把幾個關鍵字「rails google maps load issue」丟給 Google 大神求援時,發現早已有多名 Rails 開發者哀嚎過了。長話短說,之所以會有這個問題,是因為 Rails 的 Turbolinks 造成(欲知詳情,請見:Pros and Cons of Turbolinks in Rails 4 Applications。)。最簡單、暴力的方式就是到 applicaton.js 中把 //=require turnolinks 這一行給刪了。

  • app/assets/javascripts/application.js

刪除後,就能解決「使用者必須要刷新頁面,地圖才會顯示」問題。點開職缺,就可以看到 Google Map 顯示了。大功告成!

  • 實際運用在作品中可以達到以下效果:

參考資料


如果覺得這篇教程有幫助,又或是你願意給我一些鼓勵和支持,歡迎至:我的作品頁面 點下「支持TA」

目前進行中 & 過往 Logdown 分享:

Comments

comments powered by Disqus