google map API Geocorder を使ってみた(その1)

map3

今回はgoogle maps APIです。
まぁ、普通にAPI叩いて地図をウェブページ内に表示するだけだと、非常に簡単なんですが、
住所(例:秋葉原駅) から、 緯度・軽度情報の取得(該当場所にマーカーをたてる)などの処理はジオコーディングというそうで、Geocordingクラスを使う必要がります。

この辺がちょっとややこしかったので要点だけまとめておいてエントリー。
後で自分が見る用でもある。

なお、公式のドキュメントはこちら
https://developers.google.com/maps/documentation/geocoding/?hl=ja

 

なにはともあれ、MAPをhtmlに埋め込んでみる

とりあえず、基本形っていう事で。

HTML

<div id="map_canvas" style="width:500px; height:300px"></div>

js

function initialize(){
   var latlng = new google.maps.LatLng(35.697456,139.702148);
   var opts = {
      zoom:10,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
   };

   map = new google.maps.Map(document.getElementById("map_canvas"), opts);
}

ソース

なお、HTML側でgoogleMapAPIのjsを読み込むのを忘れずに。
現時点ではアプリケーションキーを埋め込まないと動かないので、ちゃんとキーも指定するでござる。

早速Geocorderを使ってみる

基本形
js

geocoder = new google.maps.Geocoder();
var address = '秋葉原';
var sendData = {'address':address, 'region':'jp'}
      geocoder.geocode( sendData,
         function(results, status){
            // コールバック関数
      });

geocoder.geocodeメソッドで位置情報が欲しい住所の文字列を送って結果を返してもらう。
結果はコールバック関数の引数でわたせる。
geocodeメソッドの第一引数は、住所文字列に日本語を使う場合は、regionの値として日本語(jp)を指定。
他にも検索範囲(bounds)とかを指定できるそうだけど、ちゃんと調べておらず。

status

コールバック関数の第2引数であるsatusはgoogle.maps.GeocoderStatusで判定可能になっている。
google.maps.GeocoderStatusオブジェクトは現時点では以下だそうです。

“OK”: エラーが発生せず、住所が正常に解析され、少なくとも 1 件のジオコードが返されたことを示します。
“ZERO_RESULTS”: ジオコードは成功しましたが、結果が返されなかったことを示します。遠隔地にある存在しない address または latlng がジオコードに渡されると、このような状態になることがあります。
“OVER_QUERY_LIMIT”: リクエストが割り当て量を超えていることを示します。
“REQUEST_DENIED”: リクエストが拒否されたことを示します。通常は、sensor パラメータが指定されていないことが原因です。
“INVALID_REQUEST”: 一般的に、クエリ(address または latlng)が不足していることを示します。

つーわけで、コールバック関数内でエラーハンドリングをする際は
status == google.maps.GeocoderStatus.OK とか
status == google.maps.GeocoderStatus.UNKNOWN_ERROR

とか指定してあげればいいっぽいね。

result

addressに”秋葉原”という文字列を指定してリクエストした結果のresultオブジェクトをdumpしてみた。
もう、めっちゃ色んな情報はいってるし。
ていうかこんな大量の情報を毎日何千万リクエスト(もっと?)さばいてるgoogle怖い
そして、こんなデータが(リクエスト回数制限はあるものの)無料で手に入る時代ってすごいね。

"results" : [
   {
      "address_components" : [
         {
            "long_name" : "秋葉原駅",
            "short_name" : "秋葉原駅",
            "types" : [ "train_station", "transit_station", "establishment" ]
         },
         {
            "long_name" : "東京都",
            "short_name" : "東京都",
            "types" : [ "administrative_area_level_1", "political" ]
         },
         {
            "long_name" : "日本",
            "short_name" : "JP",
            "types" : [ "country", "political" ]
         }
      ],
      "formatted_address" : "日本, 秋葉原駅(東京)",
      "geometry" : {
         "bounds" : {
            "northeast" : {
               "lat" : 35.7041350,
               "lng" : 139.781190
            },
            "southwest" : {
               "lat" : 35.6935090,
               "lng" : 139.7673940
            }
         },
         "location" : {
            "lat" : 35.6986830,
            "lng" : 139.7742190
         },
         "location_type" : "APPROXIMATE",
         "viewport" : {
            "northeast" : {
               "lat" : 35.7041350,
               "lng" : 139.781190
            },
            "southwest" : {
               "lat" : 35.6935090,
               "lng" : 139.7673940
            }
         }
      },
      "types" : [ "train_station", "transit_station", "establishment" ]
   }
],

まず、検索結果地図のCenterに指定される場所の名前が
address_componentsの配列先頭に格納される。
普通に考えてこれだけでいいんじゃないの って思うのだけど、その場所を含む都県の名前やその上の層である国の情報まで格納されている。
まじすげぇ
今回は秋葉原で検索したが、秋葉原駅がセットされているのがわかる。
ご丁寧に、types属性でtrain_stationと明示までされている。

では取得して表示する地図に反映したい緯度・軽度情報はどこかみてみる。
公式ドキュメントにも書いてあるように、これは geometry->location の情報を使えばいいらしい。
それ以外にもboundsやviewportなどのオブジェクトがわたされていて、lat lng値が多々入っているがこれは表示する地図の推奨する境界情報に関するデータ。複数結果が出る場合とかで威力を発揮する。

これら情報はresultの配列の中身として返ってくる事に注意すると、欲しい緯度・軽度情報は result[0]に入ることがわかるので
result[0].geometry.location
でアクセスできる。

配列で返るので注意

なぜ配列かというと、たとえばaddressで”新宿 ラーメン”などでリクエストした場合、新宿駅付近のラーメン屋と思われる位置データが複数返却され、それらが配列に格納される。
1件だけでも大量のデータなのに、ホントにすげぇな。

まとめ

以上のことをまとめると、こんな感じで住所検索が可能になる。

var geocoder;
var map;

function initialize(){
   geocoder = new google.maps.Geocoder();  // 後でつかうgeocorderオブジェクトを作っておく。
   var latlng = new google.maps.LatLng(35.697456,139.702148); //一番最初にHTMLが表示されたときの位置
   var opts = {
      zoom:15,  // ズームレベル(値を大きくしていくと細かい地図になっていく)
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
   };

   map = new google.maps.Map(document.getElementById("map_canvas"), opts);  // THMLへの地図の埋め込み
}

function codeAddress(){
   var address = document.getElementById("address").value;
   if(geocoder){
      var sendData = {'address':address, 'region':'jp'}
      geocoder.geocode( sendData,
         function(results, status){
            if(status == google.maps.GeocoderStatus.OK){
               map.setCenter(results[0].geometry.location);  // ここで地図の切り替え
            }else{
               alert("Geocode get Error. Status => " + status);

            }
      });
   }
}

次回は地図の真ん中にピン っていうかマーカーを表示する件のメモを投稿します。
おわり。

2013-07-15 | Posted in googleAPIsNo Comments » 


関連記事

Comment





Comment



*