前回までで、ほぼ欲しいものが出来上がりました。
- 地図の表示と緯度経度の取得[GoogleMapsAPIVersion3]
- マーカーと情報ウィンドウの表示と削除[GoogleMapsAPIVersion3]
- XMLを読み込んでマーカーを表示する[jQuery]+[GoogleMapsAPIVersion3]
- 表示されているマーカーのリストを表示する[jQuery]+[GoogleMapsAPIVersion3]
- リストをクリックしたら情報ウィンドウを表示する[jQuery]+[GoogleMapsAPIVersion3]
- 現在表示されている範囲内のマーカーだけ表示する[GoogleMapsAPIVersion3]+[PHP]
しかし、なんと一つ忘れていた事がありました。
ジオコーディング。
住所を入力したら、その地点が表示されるというアレです。
GoogleMapではよく使ってます。便利なんですよねー。
http://sites.google.com/site/gmapsapi3/Home/services
↑このサイトを参考にサクサクと作っていきます。
まずはジオコーディングが使えるようにおまじない。
var map; var geocoder; var marker_ary = new Array(); var currentInfoWindow function initialize() { //ジオコーディング geocoder = new google.maps.Geocoder(); var latlng = new google.maps.LatLng(34.985458, 135.757755); var myOptions = { zoom: 15, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); //イベント登録 地図の表示領域が変更されたらイベントを発生させる google.maps.event.addListener(map, 'idle', function(){ setPointMarker(); }); }
2行目と8行目ですね。
geocoder = new google.maps.Geocoder();
おまじないはこの一行で完了。
さて、肝心のジオコーディングです。
参考サイトを見ると
ジオコーディングサービスへのアクセスは非同期なため、Google Maps APIからは外部サーバーを呼び出すようにします。リクエストの実行時にコールバックを渡さなければなりません。このコールバックで結果を処理します。
とあります。
「非同期なので、リクエストと一緒に結果を受け取った後の処理も一緒に渡せよ」ちゅうことですかね。
サンプルを参考にしつつ、コードを書きます。
//ジオコーディング function codeAddress() { //入力されたアドレスを取得 var address = document.getElementById("address").value; if (geocoder) { geocoder.geocode( { 'address': address}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { //ジオコーディング結果の緯度経度を地図の中央に map.setCenter(results[0].geometry.location); //住所データ表示 document.getElementById("adrname").value = results[0].formatted_address; } else { alert("Geocode was not successful for the following reason: " + status); } }); } }
3行目で、idがaddressのテキストフィールドの文字列を引っこ抜きます。
7行目で、引っこ抜いた住所文字列をGmapに渡しています。
8行目から18行目までが、さっきのコールバックに該当する感じですね。
ちゃんと値が返ってきたら地図の真ん中を帰ってきた座標に変更します。
14行目はおまけ。
文字列に該当する緯度経度とともに、住所も帰ってくるのでついでに表示してみます。
実は、ジオコーディングで帰ってくる座標は一つとは限りません。
11行目なんかみると results[0] ってなっているのがわかると思います。
つまり、ここでは複数帰ってきても最初の一件だけを適用する仕組みになっています。
本来なら帰ってきた座標を全部表示して選択させるってのが親切なんでしょうけど、今回はこれで妥協します。
出来上がったコードはこんな感じです。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <script type="text/javascript"> var map; var geocoder; var marker_ary = new Array(); var currentInfoWindow function initialize() { //ジオコーディング geocoder = new google.maps.Geocoder(); var latlng = new google.maps.LatLng(34.985458, 135.757755); var myOptions = { zoom: 15, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); //イベント登録 地図の表示領域が変更されたらイベントを発生させる google.maps.event.addListener(map, 'idle', function(){ setPointMarker(); }); } //地図中央の緯度経度を表示 function getMapcenter() { //地図中央の緯度経度を取得 var mapcenter = map.getCenter(); //テキストフィールドにセット document.getElementById("keido").value = mapcenter.lng(); document.getElementById("ido").value = mapcenter.lat(); } //地図の中央にマーカー function setMarker() { var mapCenter = map.getCenter(); //マーカー削除 MarkerClear(); //マーカー表示 MarkerSet(mapCenter.lat(),mapCenter.lng(),'test'); } //マーカー削除 function MarkerClear() { //表示中のマーカーがあれば削除 if(marker_ary.length > 0){ //マーカー削除 for (i = 0; i < marker_ary.length; i++) { marker_ary[i].setMap(); } //配列削除 for (i = 0; i <= marker_ary.length; i++) { marker_ary.shift(); } } } function MarkerSet(lat,lng,text){ var marker_num = marker_ary.length; var marker_position = new google.maps.LatLng(lat,lng); var markerOpts = { map: map, position: marker_position }; marker_ary[marker_num] = new google.maps.Marker(markerOpts); //textが渡されていたらふきだしをセット if(text.length>0){ var infoWndOpts = { content : text }; var infoWnd = new google.maps.InfoWindow(infoWndOpts); google.maps.event.addListener(marker_ary[marker_num], "click", function(){ //先に開いた情報ウィンドウがあれば、closeする if (currentInfoWindow) { currentInfoWindow.close(); } //情報ウィンドウを開く infoWnd.open(map, marker_ary[marker_num]); //開いた情報ウィンドウを記録しておく currentInfoWindow = infoWnd; }); } } //XMLで取得した地点を地図上でマーカーに表示 function setPointMarker(){ //リストの内容を削除 $('#pointlist > ul').empty(); //マーカー削除 MarkerClear(); //地図の範囲内を取得 var bounds = map.getBounds(); map_ne_lat = bounds.getNorthEast().lat(); map_sw_lat = bounds.getSouthWest().lat(); map_ne_lng = bounds.getNorthEast().lng(); map_sw_lng = bounds.getSouthWest().lng(); //XML取得 $.ajax({ url: 'xml.php?ne_lat='+map_ne_lat+'&sw_lat='+map_sw_lat+'&ne_lng='+map_ne_lng+'&sw_lng='+map_sw_lng, type: 'GET', dataType: 'xml', timeout: 1000, error: function(){ alert("情報の読み込みに失敗しました"); }, success: function(xml){ //帰ってきた地点の数だけループ $(xml).find("Locate").each(function(){ var LocateLat = $("lat",this).text(); var LocateLng = $("lng",this).text(); var LocateName = $("name",this).text(); //マーカーをセット MarkerSet(LocateLat,LocateLng,LocateName); //リスト表示 //リストに対応するマーカー配列キーをセット var marker_num = marker_ary.length - 1; //liとaタグをセット loc = $('<li>').append($('<a href="javascript:void(0)"/>').text(LocateName)); //セットしたタグにイベント「マーカーがクリックされた」をセット loc.bind('click', function(){ google.maps.event.trigger(marker_ary[marker_num], 'click'); }); //リスト表示 $('#pointlist > ul').append(loc); }); } }); } //ジオコーディング function codeAddress() { //入力されたアドレスを取得 var address = document.getElementById("address").value; if (geocoder) { geocoder.geocode( { 'address': address}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { //ジオコーディング結果の緯度経度を地図の中央に map.setCenter(results[0].geometry.location); //住所データ表示 document.getElementById("adrname").value = results[0].formatted_address; } else { alert("Geocode was not successful for the following reason: " + status); } }); } } </script> </head> <body onload="initialize()"> <div id="pointlist" style="width:20em;float:left;"> <ul> <li>地点リスト</li> </ul> </div> <div style="float:left;"> <div id="map_canvas" style="width:600px; height:600px"></div> <div> 経度<input type="text" size="20" id="ido" value="" /> 緯度<input type="text" size="20" id="keido" value="" /> <input type="button" value="地図中央の緯度経度" onclick="getMapcenter()" onkeypress="getMapcenter()" /> <div> <div> <input type="text" size="20" id="address" value="" /><input type="button" value="←ジオコーディング" onclick="codeAddress()" onkeypress="getMapcenter()" /> 住所:<input type="text" size="20" id="adrname" value="" /> <div> </div> </body> </html>
サンプルはこちら →動作サンプル
ちょっと中途半端ですが、この記事、長い間塩漬けにしていたのでとりあえずアップします。
次は逆ジオコーディングについて書きます。