2013年3月10日 星期日

【Google Maps】(一) 初始化地圖與透過地址轉換經緯度重新定位地圖位置

一年前因為專案需求,曾經研究google map一段時間,最近東翻西找終於找到之前練習的程式碼,想說要來整理整理,但因為,我想很多人都知道,api麻,總是有可能會更新的(例如:Facebook就是一個很好的例子>"<),所以還是需要重新上官網看看有沒有差異、並且重新回憶一下~

一上官網我就先疑惑了一下,因為記得之前研究時官網上說,v3版已經不需要申請金鑰即可使用,但這次...
http://goo.gl/EuNd5  這裡說要金鑰!!!?
http://goo.gl/iDeDa   這裡又說已經不用!!!?
我都糊塗了 囧 ㄚㄚㄚㄚ~~~

好吧,說實話我真的很懶,我懶得再去爬官網上的蛛絲馬跡,
網路上看到兩篇文章提到...

這裡 http://goo.gl/Yc0tU 和這裡 http://goo.gl/pLf02

所以...同一頁面免費存取次數為25000次,超過才需收費!?
我只是想demo~~應該不用吧!? 哈哈哈 (不負責任發言XD)

預先看線上demo請點我




關於Google Maps API的入門使用,其實官網寫得非常清楚,而且也非常貼心的已經出現中文版說明,所以想要觀看詳細說明步驟可至官網查看,以下是針對本demo範例內的程式碼做說明。

Html部分:
 
  
請輸入地址:
【您輸入的地址位置】
【移動標記點後的位置】

地址輸入框 輸入地址後,地圖及標記點會重新定位,下方id=SearchLatLng的div區塊也會及時顯示目前定位點的經緯度。
id=NowLatLng的div區塊 若移動標記點,此區塊會顯示移動定位點後,新的經緯度。
id=map_canvas的div區塊 用來顯示地圖的預留區塊。

CSS部分:
 
  html { height: 100% }
  body { height: 100%; margin: 0 20%; padding: 0px }
  #map_canvas { height: 100% }

官網上的說明:這個 CSS 宣告地圖容器id=map_canvas的div區塊應使用 HTML 主體的 100% 高度。也必須特別宣告 body 和 html 的百分比。

記得第一次研究時原本以為這些css只是單純要定位地圖在網頁上的某個位置,所以原本以為height: 100%可有可無,以為就算不去定義還是會自動撐開,可是測試結果卻是不會,所以我還是乖乖的定義了高度...

JS部分:
首先,先載入必要的檔案:
 



https://maps.google.com/maps/api/js?sensor=false
  • 載入Google Maps API的基本js檔,如需使用其他程式庫,必須使用 libraries 參數選擇性地載入,如需使用可查看官網程式庫
  • sensor參數官網上的說明:指出這個應用程式是否要使用感應器 (例如 GPS 定位器) 判斷使用者的位置。但由於我不管設true or false都看不出有甚麼差異,所以直接設flase..
  • 除了sensor參數,現階段官網上還有key參數用來設定API金鑰,但由於文章開頭提到的原因,所以這裡不使用。
jquery-1.7.2.min.js 必須先載入jquery的js檔,後續才能使用相關的jquery語法

若只是單純初始化地圖並定位,程式碼只需要:
 
    //初始化地圖時的定位經緯度設定
    var latlng = new google.maps.LatLng(23.973875,120.982024); //台灣緯度Latitude、經度Longitude:23.973875,120.982024
    //初始化地圖options設定
    var mapOptions = {
      zoom: 10,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    //初始化地圖
    map = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);

上述mapOptions的其餘設定值可至官網查看,其中mapTypeId共有四個設定值:
HYBRID 衛星圖樣式,有道路顯示。
ROADMAP 一般開啟google map最一開始看到的黃底道路樣式。
SATELLITE 衛星圖樣式,無道路顯示。
TERRAIN 依造地理特性顯示,如:地形。


若要在初始化後的地圖定位點上顯示標記點Marker,則程式碼要再補上:
 
    //加入標記點
    marker = new google.maps.Marker({
     draggable:true,
     position: latlng,
     title:"台灣 Taiwan",
     map:map
    }); 

draggable 設定標記點Marker是否可拖曳,預設值為false。
position 標記點Marker的位置。
title 標記點Marker在mouseover時顯示的文字。
map 要顯示標記點Marker的地圖物件。
標記點Marker還有其他可供設定的option可至官網查看。

接著,地址與經緯度轉換部分要使用google.maps.Geocoder類別,程式碼主要為:
 
 geocoder = new google.maps.Geocoder();
 geocoder.geocode(
   {
      'address':address //此處帶入Request屬性
   },function (results,status) 
   {
      if(status==google.maps.GeocoderStatus.OK) 
      {
      
      }
   }
 ); 

Request屬性 要傳給google.maps.Geocoder屬性值,由於需求是以地址求經緯度所以輸入address。其餘屬性請查看
callback回傳的第1參數results 執行後的結果資料,詳細內容請查看
callback回傳的第2參數status 執行狀態,成功則顯示OK,或其他例外的Status可至官網查看。

最後,由於demo範例需求為:
1. 地址輸入框一有變動就需立即重新定位地圖位置,並顯示目前位置的經緯度
2. 若是用滑鼠拖曳標記點Marker則顯示移動後位置的經緯度
所以需另外處理input的keyup事件與Google Maps中Marker的mouseup事件。


以下是本次demo詳細JS部分:
 
  var map;
  var marker;
   
  function initialize() 
  {
    //初始化地圖時的定位經緯度設定
    var latlng = new google.maps.LatLng(23.973875,120.982024); //台灣緯度Latitude、經度Longitude:23.973875,120.982024
    //初始化地圖options設定
    var mapOptions = {
        zoom: 10,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    //初始化地圖
    map = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);
    //加入標記點
    marker = new google.maps.Marker({
       draggable:true,
       position: latlng,
       title:"台灣 Taiwan",
       map:map
    }); 
    //增加標記點的mouseup事件
    google.maps.event.addListener(marker, 'mouseup', function() {
        LatLng = marker.getPosition();
        $("#NowLatLng").html("【移動標記點後的位置】緯度:" + LatLng.lat() + "經度:" + LatLng.lng());
    });
 
  }
  
  function GetAddressMarker()
  {//重新定位地圖位置與標記點位置
  address = $("#address_val").val();
  geocoder = new google.maps.Geocoder();
  geocoder.geocode(
   {
    'address':address
   },function (results,status) 
   {
   if(status==google.maps.GeocoderStatus.OK) 
   {
      //console.log(results[0].geometry.location);
      LatLng = results[0].geometry.location;
      map.setCenter(LatLng);  //將地圖中心定位到查詢結果
      marker.setPosition(LatLng); //將標記點定位到查詢結果
      marker.setTitle(address); //重新設定標記點的title
      $("#SearchLatLng").html("【您輸入的地址位置】緯度:" + LatLng.lat() + "經度:" + LatLng.lng());
   }
   }
  ); 
  }
  
  $(document).ready(function() { 
    //綁定地址輸入框的keyup事件以即時重新定位
    $("#address_val").bind("keyup",function(){ 
      GetAddressMarker();
      $("#NowLatLng").html("【移動標記點後的位置】");
    }); 
  });

【2017/9/16更新】

最近整理失效的demo連結(換位置啦XD)時發現,Google Maps API已經需要金鑰囉!金鑰如何申請可參考【Youtube】(一)如何申請Youtube Data API v3金鑰?這篇~

如果您喜歡我的分享、或是我的文章對您有幫助的話,希望能到我的粉絲專頁點個讚追蹤我唷~~

寫程式、技術分享文章很辛苦,寫一篇要花非常久的時間,希望您能幫我點一下頁面上的廣告給我支持跟肯定,讓我更有動力寫這類文章唷~

17 則留言:

  1. 請問一下如果我的資料庫已經有了五所有要的地方的經緯度
    並且json也已經做好了
    但我要怎麼讓我的google map把所有我要的地標呈現在地圖上呢?

    回覆刪除
    回覆
    1. 您好
      關於您的問題,您可以先參考我下一篇文章:
      【Google Maps】(二)資訊視窗infowindow與MarkerClusterer

      裡頭詳細JS部分應該就有您要的答案囉~ ^_^

      刪除
    2. 謝謝您,我會再研究看看的^^

      刪除
  2. 請問 我是用 click 新增 marker 可以抓到經緯度
    但是目前解決不了 將經緯度轉換成地址的方式 可以交一下嗎

    回覆刪除
    回覆
    1. 您好
      我之前看Geocoder可帶參數值的官方文件http://goo.gl/oQNf6J
      這裡有提到 其中一項就是location經緯度資訊
      我也曾想過 既然可以帶經緯度 是否可以轉成地址

      但因為我覺得轉成地址一定誤差很大 (門號之類的)
      所以我沒試過用經緯度轉換成地址

      我剛在Geocoder回傳結果值的官方文件http://goo.gl/fSh5Bt
      這裡有看到下面這段:

      formatted_address 這個字串包含這個位置的人類可讀地址。通常,這個地址即等於「郵政地址」,有時郵寄地址會因為國家/地區而不同 (請注意,因為授權限制,部分國家/地區 (例如英國) 並不允許散佈真實的郵政地址)。這個地址一般是由一或多個「地址元件」所組成。舉例來說,「111 8th Avenue, New York, NY」這個地址就包含「111」(街道號碼)、「8th Avenue」(路線)、「New York」(城市名稱) 和「NY」(美國州名) 等個別地址元件。這些地址元件包含下列其他資訊。

      我有大概試了一下
      參數帶入 : location經緯度資訊
      結果值 : 以formatted_address接收

      結果確實是出現地址唷
      只是我不太確定會不會誤差就是了

      刪除
  3. 您好, 有拜讀另一篇您的文章關於拖曳產生圓, 請問如果僅要點選 maker 就顯示一個半徑500m的圓圈, 該如何處理, 又該如何關閉那個被開啟的圓呢 ?

    回覆刪除
    回覆
    1. 您好
      我不太懂您說的是我哪篇文章
      拖曳產生圓中的「圓」
      指的是infowindow資訊視窗嗎?

      刪除
  4. 不好意思 我想寫個andorid 地圖 可是我要標籤地址 我的地址都存在excel 要抓那些地址去標在地圖上 請問大要怎做 現在只有把地圖叫出來而已 知道的麻煩 感謝

    回覆刪除
    回覆
    1. 您好
      不曉得您說的「標籤地址」指的是標記點嗎!?

      如果是的話
      針對單一地址作標記點
      您可查看本篇文章
      透過google提供的geocoder與Marker即可達成

      針對多地址分別作標記點的話
      我想您的問題應該類似本篇文章第一位網友「林靜」的問題
      你可以參照我的另一篇文章搭配閱讀:

      【Google Maps】(二)資訊視窗infowindow與MarkerClusterer

      我想這裡頭應該就有你需要的部分了

      刪除
  5. 我想寫個app 然後要標籤很多地址在地圖上
    就是地址上面有個圖片 所在位置
    然後大概有735筆地址存在excel檔csv檔
    然後想請問我該怎麼做比較好
    目前有點卡住了 感謝老師

    回覆刪除
    回覆
    1. 恩....所以你卡住的地方
      該不會是 怎麼從csv(excel)讀取地址資料!?
      ( 應該不是吧XD 如果是的話你好像就問錯地方了... )

      照你兩次描述的內容 我理解的是:

      標記多個地址在地圖上
      每個地址上有個圖片
      (這點是說 每個地址上會出現類似泡泡框而且裡頭有圖片嗎!?)

      如果我理解沒有錯
      應該就是我上一篇回覆的
      我另一篇文章應該就是你要的囉...

      刪除
  6. 您好,由於時常需要Google Map方面的API
    我是否可將這篇文章的連結及範例轉貼至我的版
    P.S:我會註明是轉帖的

    回覆刪除
    回覆
    1. 如果只是貼網址連結是ok的,但如果是文章內容可能就不方便囉~

      刪除
  7. 如果要從geocoder.geocode裡面將計算好的經緯度取出給自訂變數
    這個有辦法嗎!
    試了一下午,就是取不出來!
    我的做法是設個全域變數陣列
    在geocoder.geocode將經緯度push進全域變數陣列
    這樣會失敗…

    回覆刪除
    回覆
    1. 從geocoder.geocode的callback裡取得的經緯度指定給自訂變數
      你都已經設為全域變數了
      我想 理論上應該是可以的
      不曉得您測試失敗的程式碼是什麼樣子呢?

      刪除
  8. 先來感謝先~XD
    好加在有找到這篇.....
    不然我想我會改很久~XDDDDDD

    回覆刪除

writing for work~writing for life~